aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-02-01 19:26:59 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-02-01 19:26:59 +0000
commit86babf4bfda7c2c2e9be4abc20e4d8073e05e5be (patch)
tree7e7e6083ebe59999943a211a17f8ef6f07f17c2f /libgo
parentdf9ff8bf53f716508a120d15cc144e628fd2e9b5 (diff)
libgo: Update to weekly.2012-01-27.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183810 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am425
-rw-r--r--libgo/Makefile.in536
-rw-r--r--libgo/go/archive/tar/reader.go8
-rw-r--r--libgo/go/archive/tar/reader_test.go27
-rw-r--r--libgo/go/archive/zip/reader.go24
-rw-r--r--libgo/go/archive/zip/reader_test.go24
-rw-r--r--libgo/go/archive/zip/struct.go38
-rw-r--r--libgo/go/archive/zip/writer.go2
-rw-r--r--libgo/go/archive/zip/zip_test.go20
-rw-r--r--libgo/go/bytes/buffer.go50
-rw-r--r--libgo/go/compress/flate/deflate.go105
-rw-r--r--libgo/go/compress/flate/deflate_test.go44
-rw-r--r--libgo/go/compress/flate/huffman_bit_writer.go26
-rw-r--r--libgo/go/compress/flate/huffman_code.go4
-rw-r--r--libgo/go/compress/flate/util.go72
-rw-r--r--libgo/go/compress/gzip/gunzip.go14
-rw-r--r--libgo/go/compress/gzip/gunzip_test.go6
-rw-r--r--libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt8858
-rw-r--r--libgo/go/compress/zlib/reader.go12
-rw-r--r--libgo/go/compress/zlib/reader_test.go6
-rw-r--r--libgo/go/crypto/bcrypt/base64.go35
-rw-r--r--libgo/go/crypto/bcrypt/bcrypt.go282
-rw-r--r--libgo/go/crypto/bcrypt/bcrypt_test.go194
-rw-r--r--libgo/go/crypto/blowfish/block.go192
-rw-r--r--libgo/go/crypto/blowfish/blowfish_test.go210
-rw-r--r--libgo/go/crypto/blowfish/cipher.go100
-rw-r--r--libgo/go/crypto/blowfish/const.go199
-rw-r--r--libgo/go/crypto/cast5/cast5.go534
-rw-r--r--libgo/go/crypto/cast5/cast5_test.go104
-rw-r--r--libgo/go/crypto/dsa/dsa.go6
-rw-r--r--libgo/go/crypto/md4/md4.go118
-rw-r--r--libgo/go/crypto/md4/md4_test.go71
-rw-r--r--libgo/go/crypto/md4/md4block.go89
-rw-r--r--libgo/go/crypto/ocsp/ocsp.go191
-rw-r--r--libgo/go/crypto/ocsp/ocsp_test.go107
-rw-r--r--libgo/go/crypto/openpgp/armor/armor.go219
-rw-r--r--libgo/go/crypto/openpgp/armor/armor_test.go95
-rw-r--r--libgo/go/crypto/openpgp/armor/encode.go160
-rw-r--r--libgo/go/crypto/openpgp/canonical_text.go59
-rw-r--r--libgo/go/crypto/openpgp/canonical_text_test.go52
-rw-r--r--libgo/go/crypto/openpgp/elgamal/elgamal.go122
-rw-r--r--libgo/go/crypto/openpgp/elgamal/elgamal_test.go49
-rw-r--r--libgo/go/crypto/openpgp/errors/errors.go64
-rw-r--r--libgo/go/crypto/openpgp/keys.go546
-rw-r--r--libgo/go/crypto/openpgp/packet/compressed.go38
-rw-r--r--libgo/go/crypto/openpgp/packet/compressed_test.go41
-rw-r--r--libgo/go/crypto/openpgp/packet/encrypted_key.go167
-rw-r--r--libgo/go/crypto/openpgp/packet/encrypted_key_test.go126
-rw-r--r--libgo/go/crypto/openpgp/packet/literal.go89
-rw-r--r--libgo/go/crypto/openpgp/packet/one_pass_signature.go73
-rw-r--r--libgo/go/crypto/openpgp/packet/packet.go482
-rw-r--r--libgo/go/crypto/openpgp/packet/packet_test.go255
-rw-r--r--libgo/go/crypto/openpgp/packet/private_key.go310
-rw-r--r--libgo/go/crypto/openpgp/packet/private_key_test.go58
-rw-r--r--libgo/go/crypto/openpgp/packet/public_key.go414
-rw-r--r--libgo/go/crypto/openpgp/packet/public_key_test.go99
-rw-r--r--libgo/go/crypto/openpgp/packet/reader.go62
-rw-r--r--libgo/go/crypto/openpgp/packet/signature.go611
-rw-r--r--libgo/go/crypto/openpgp/packet/signature_test.go42
-rw-r--r--libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go161
-rw-r--r--libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go101
-rw-r--r--libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go289
-rw-r--r--libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go124
-rw-r--r--libgo/go/crypto/openpgp/packet/userid.go160
-rw-r--r--libgo/go/crypto/openpgp/packet/userid_test.go87
-rw-r--r--libgo/go/crypto/openpgp/read.go414
-rw-r--r--libgo/go/crypto/openpgp/read_test.go372
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k.go183
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k_test.go118
-rw-r--r--libgo/go/crypto/openpgp/write.go315
-rw-r--r--libgo/go/crypto/openpgp/write_test.go232
-rw-r--r--libgo/go/crypto/ripemd160/ripemd160.go120
-rw-r--r--libgo/go/crypto/ripemd160/ripemd160_test.go64
-rw-r--r--libgo/go/crypto/ripemd160/ripemd160block.go161
-rw-r--r--libgo/go/crypto/tls/root_stub.go2
-rw-r--r--libgo/go/crypto/twofish/twofish.go355
-rw-r--r--libgo/go/crypto/twofish/twofish_test.go129
-rw-r--r--libgo/go/crypto/xtea/block.go66
-rw-r--r--libgo/go/crypto/xtea/cipher.go89
-rw-r--r--libgo/go/crypto/xtea/xtea_test.go246
-rw-r--r--libgo/go/database/sql/convert.go9
-rw-r--r--libgo/go/database/sql/fakedb_test.go14
-rw-r--r--libgo/go/database/sql/sql.go120
-rw-r--r--libgo/go/database/sql/sql_test.go187
-rw-r--r--libgo/go/encoding/binary/varint.go19
-rw-r--r--libgo/go/encoding/binary/varint_test.go32
-rw-r--r--libgo/go/encoding/git85/git.go276
-rw-r--r--libgo/go/encoding/git85/git_test.go194
-rw-r--r--libgo/go/encoding/gob/debug.go3
-rw-r--r--libgo/go/encoding/gob/decoder.go4
-rw-r--r--libgo/go/encoding/gob/gobencdec_test.go1
-rw-r--r--libgo/go/encoding/xml/marshal.go129
-rw-r--r--libgo/go/encoding/xml/marshal_test.go102
-rw-r--r--libgo/go/encoding/xml/read.go80
-rw-r--r--libgo/go/encoding/xml/read_test.go9
-rw-r--r--libgo/go/encoding/xml/typeinfo.go3
-rw-r--r--libgo/go/encoding/xml/xml.go482
-rw-r--r--libgo/go/encoding/xml/xml_test.go81
-rw-r--r--libgo/go/exp/ebnflint/ebnflint.go41
-rw-r--r--libgo/go/exp/ebnflint/ebnflint_test.go16
-rw-r--r--libgo/go/exp/html/const.go (renamed from libgo/go/html/const.go)0
-rw-r--r--libgo/go/exp/html/doc.go (renamed from libgo/go/html/doc.go)0
-rw-r--r--libgo/go/exp/html/doctype.go (renamed from libgo/go/html/doctype.go)0
-rw-r--r--libgo/go/exp/html/entity.go2253
-rw-r--r--libgo/go/exp/html/entity_test.go29
-rw-r--r--libgo/go/exp/html/escape.go253
-rw-r--r--libgo/go/exp/html/foreign.go (renamed from libgo/go/html/foreign.go)0
-rw-r--r--libgo/go/exp/html/node.go (renamed from libgo/go/html/node.go)0
-rw-r--r--libgo/go/exp/html/parse.go (renamed from libgo/go/html/parse.go)0
-rw-r--r--libgo/go/exp/html/parse_test.go (renamed from libgo/go/html/parse_test.go)0
-rw-r--r--libgo/go/exp/html/render.go (renamed from libgo/go/html/render.go)0
-rw-r--r--libgo/go/exp/html/render_test.go (renamed from libgo/go/html/render_test.go)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/README (renamed from libgo/go/html/testdata/webkit/README)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/adoption01.dat (renamed from libgo/go/html/testdata/webkit/adoption01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/adoption02.dat (renamed from libgo/go/html/testdata/webkit/adoption02.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/comments01.dat (renamed from libgo/go/html/testdata/webkit/comments01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/doctype01.dat (renamed from libgo/go/html/testdata/webkit/doctype01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/entities01.dat (renamed from libgo/go/html/testdata/webkit/entities01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/entities02.dat (renamed from libgo/go/html/testdata/webkit/entities02.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/html5test-com.dat (renamed from libgo/go/html/testdata/webkit/html5test-com.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/inbody01.dat (renamed from libgo/go/html/testdata/webkit/inbody01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/isindex.dat (renamed from libgo/go/html/testdata/webkit/isindex.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat (renamed from libgo/go/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat)bin115 -> 115 bytes
-rw-r--r--libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat (renamed from libgo/go/html/testdata/webkit/pending-spec-changes.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/plain-text-unsafe.dat (renamed from libgo/go/html/testdata/webkit/plain-text-unsafe.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/scriptdata01.dat (renamed from libgo/go/html/testdata/webkit/scriptdata01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/scripted/adoption01.dat (renamed from libgo/go/html/testdata/webkit/scripted/adoption01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/scripted/webkit01.dat (renamed from libgo/go/html/testdata/webkit/scripted/webkit01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tables01.dat (renamed from libgo/go/html/testdata/webkit/tables01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests1.dat (renamed from libgo/go/html/testdata/webkit/tests1.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests10.dat (renamed from libgo/go/html/testdata/webkit/tests10.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests11.dat (renamed from libgo/go/html/testdata/webkit/tests11.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests12.dat (renamed from libgo/go/html/testdata/webkit/tests12.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests14.dat (renamed from libgo/go/html/testdata/webkit/tests14.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests15.dat (renamed from libgo/go/html/testdata/webkit/tests15.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests16.dat (renamed from libgo/go/html/testdata/webkit/tests16.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests17.dat (renamed from libgo/go/html/testdata/webkit/tests17.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests18.dat (renamed from libgo/go/html/testdata/webkit/tests18.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests19.dat (renamed from libgo/go/html/testdata/webkit/tests19.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests2.dat (renamed from libgo/go/html/testdata/webkit/tests2.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests20.dat (renamed from libgo/go/html/testdata/webkit/tests20.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests21.dat (renamed from libgo/go/html/testdata/webkit/tests21.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests22.dat (renamed from libgo/go/html/testdata/webkit/tests22.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests23.dat (renamed from libgo/go/html/testdata/webkit/tests23.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests24.dat (renamed from libgo/go/html/testdata/webkit/tests24.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests25.dat (renamed from libgo/go/html/testdata/webkit/tests25.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests26.dat (renamed from libgo/go/html/testdata/webkit/tests26.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests3.dat (renamed from libgo/go/html/testdata/webkit/tests3.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests4.dat (renamed from libgo/go/html/testdata/webkit/tests4.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests5.dat (renamed from libgo/go/html/testdata/webkit/tests5.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests6.dat (renamed from libgo/go/html/testdata/webkit/tests6.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests7.dat (renamed from libgo/go/html/testdata/webkit/tests7.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests8.dat (renamed from libgo/go/html/testdata/webkit/tests8.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests9.dat (renamed from libgo/go/html/testdata/webkit/tests9.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat (renamed from libgo/go/html/testdata/webkit/tests_innerHTML_1.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/tricky01.dat (renamed from libgo/go/html/testdata/webkit/tricky01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/webkit01.dat (renamed from libgo/go/html/testdata/webkit/webkit01.dat)0
-rw-r--r--libgo/go/exp/html/testdata/webkit/webkit02.dat (renamed from libgo/go/html/testdata/webkit/webkit02.dat)0
-rw-r--r--libgo/go/exp/html/token.go (renamed from libgo/go/html/token.go)0
-rw-r--r--libgo/go/exp/html/token_test.go (renamed from libgo/go/html/token_test.go)0
-rw-r--r--libgo/go/exp/norm/tables.go109
-rw-r--r--libgo/go/exp/norm/triegen.go4
-rw-r--r--libgo/go/exp/spdy/read.go312
-rw-r--r--libgo/go/exp/spdy/spdy_test.go497
-rw-r--r--libgo/go/exp/spdy/types.go369
-rw-r--r--libgo/go/exp/spdy/write.go285
-rw-r--r--libgo/go/exp/ssh/channel.go318
-rw-r--r--libgo/go/exp/ssh/cipher.go88
-rw-r--r--libgo/go/exp/ssh/cipher_test.go62
-rw-r--r--libgo/go/exp/ssh/client.go505
-rw-r--r--libgo/go/exp/ssh/client_auth.go316
-rw-r--r--libgo/go/exp/ssh/client_auth_test.go257
-rw-r--r--libgo/go/exp/ssh/client_func_test.go61
-rw-r--r--libgo/go/exp/ssh/common.go239
-rw-r--r--libgo/go/exp/ssh/common_test.go26
-rw-r--r--libgo/go/exp/ssh/doc.go127
-rw-r--r--libgo/go/exp/ssh/messages.go640
-rw-r--r--libgo/go/exp/ssh/messages_test.go125
-rw-r--r--libgo/go/exp/ssh/server.go676
-rw-r--r--libgo/go/exp/ssh/server_terminal.go81
-rw-r--r--libgo/go/exp/ssh/session.go494
-rw-r--r--libgo/go/exp/ssh/session_test.go374
-rw-r--r--libgo/go/exp/ssh/tcpip.go132
-rw-r--r--libgo/go/exp/ssh/tcpip_func_test.go59
-rw-r--r--libgo/go/exp/ssh/transport.go369
-rw-r--r--libgo/go/exp/ssh/transport_test.go51
-rw-r--r--libgo/go/go/ast/import.go7
-rw-r--r--libgo/go/go/build/build.go425
-rw-r--r--libgo/go/go/build/build_test.go56
-rw-r--r--libgo/go/go/build/dir.go128
-rw-r--r--libgo/go/go/build/path.go22
-rw-r--r--libgo/go/go/doc/doc.go89
-rw-r--r--libgo/go/go/doc/doc_test.go12
-rw-r--r--libgo/go/go/doc/exports.go126
-rw-r--r--libgo/go/go/doc/filter.go13
-rw-r--r--libgo/go/go/doc/reader.go1029
-rw-r--r--libgo/go/go/doc/testdata/a.0.golden (renamed from libgo/go/go/doc/testdata/a.out)0
-rw-r--r--libgo/go/go/doc/testdata/a.1.golden13
-rw-r--r--libgo/go/go/doc/testdata/b.0.golden (renamed from libgo/go/go/doc/testdata/b.out)9
-rw-r--r--libgo/go/go/doc/testdata/b.1.golden49
-rw-r--r--libgo/go/go/doc/testdata/b.go17
-rw-r--r--libgo/go/go/doc/testdata/c.0.golden48
-rw-r--r--libgo/go/go/doc/testdata/c.1.golden48
-rw-r--r--libgo/go/go/doc/testdata/c.go62
-rw-r--r--libgo/go/go/doc/testdata/d.0.golden104
-rw-r--r--libgo/go/go/doc/testdata/d.1.golden104
-rw-r--r--libgo/go/go/doc/testdata/d1.go57
-rw-r--r--libgo/go/go/doc/testdata/d2.go45
-rw-r--r--libgo/go/go/doc/testdata/e.0.golden31
-rw-r--r--libgo/go/go/doc/testdata/e.1.golden61
-rw-r--r--libgo/go/go/doc/testdata/e.go58
-rw-r--r--libgo/go/go/doc/testdata/testing.0.golden (renamed from libgo/go/go/doc/testdata/testing.out)0
-rw-r--r--libgo/go/go/doc/testdata/testing.1.golden298
-rw-r--r--libgo/go/go/parser/interface.go15
-rw-r--r--libgo/go/go/parser/parser.go6
-rw-r--r--libgo/go/go/printer/nodes.go90
-rw-r--r--libgo/go/go/printer/printer.go30
-rw-r--r--libgo/go/go/printer/testdata/declarations.golden50
-rw-r--r--libgo/go/go/printer/testdata/linebreaks.golden52
-rw-r--r--libgo/go/go/printer/testdata/linebreaks.input48
-rw-r--r--libgo/go/go/scanner/scanner.go12
-rw-r--r--libgo/go/go/scanner/scanner_test.go2
-rw-r--r--libgo/go/html/escape.go4
-rw-r--r--libgo/go/io/ioutil/ioutil.go17
-rw-r--r--libgo/go/math/big/arith.go21
-rw-r--r--libgo/go/math/big/arith_decl.go1
-rw-r--r--libgo/go/math/big/arith_test.go37
-rw-r--r--libgo/go/net/cgo_stub.go2
-rw-r--r--libgo/go/net/dial.go181
-rw-r--r--libgo/go/net/dialgoogle_test.go2
-rw-r--r--libgo/go/net/dict/dict.go210
-rw-r--r--libgo/go/net/fd.go19
-rw-r--r--libgo/go/net/fd_windows.go17
-rw-r--r--libgo/go/net/http/client.go4
-rw-r--r--libgo/go/net/http/client_test.go12
-rw-r--r--libgo/go/net/http/readrequest_test.go76
-rw-r--r--libgo/go/net/http/request.go36
-rw-r--r--libgo/go/net/http/request_test.go19
-rw-r--r--libgo/go/net/http/transport.go18
-rw-r--r--libgo/go/net/http/transport_test.go56
-rw-r--r--libgo/go/net/ipraw_test.go228
-rw-r--r--libgo/go/net/iprawsock_plan9.go41
-rw-r--r--libgo/go/net/iprawsock_posix.go85
-rw-r--r--libgo/go/net/lookup_plan9.go5
-rw-r--r--libgo/go/net/rpc/client.go1
-rw-r--r--libgo/go/net/rpc/server_test.go13
-rw-r--r--libgo/go/net/sock.go1
-rw-r--r--libgo/go/net/sockopt.go12
-rw-r--r--libgo/go/net/tcpsock_plan9.go4
-rw-r--r--libgo/go/net/tcpsock_posix.go4
-rw-r--r--libgo/go/net/timeout_test.go27
-rw-r--r--libgo/go/net/udp_test.go87
-rw-r--r--libgo/go/net/udpsock_plan9.go6
-rw-r--r--libgo/go/net/udpsock_posix.go38
-rw-r--r--libgo/go/net/unixsock_posix.go6
-rw-r--r--libgo/go/os/file_plan9.go51
-rw-r--r--libgo/go/os/stat_plan9.go5
-rw-r--r--libgo/go/os/user/lookup_stubs.go2
-rw-r--r--libgo/go/patch/apply.go54
-rw-r--r--libgo/go/patch/git.go121
-rw-r--r--libgo/go/patch/patch.go321
-rw-r--r--libgo/go/patch/patch_test.go390
-rw-r--r--libgo/go/patch/textdiff.go179
-rw-r--r--libgo/go/path/filepath/path_test.go11
-rw-r--r--libgo/go/regexp/regexp.go7
-rw-r--r--libgo/go/runtime/chan_test.go9
-rw-r--r--libgo/go/runtime/debug.go3
-rw-r--r--libgo/go/runtime/extern.go3
-rw-r--r--libgo/go/websocket/client.go137
-rw-r--r--libgo/go/websocket/hixie.go695
-rw-r--r--libgo/go/websocket/hixie_test.go201
-rw-r--r--libgo/go/websocket/hybi.go549
-rw-r--r--libgo/go/websocket/hybi_test.go584
-rw-r--r--libgo/go/websocket/server.go102
-rw-r--r--libgo/go/websocket/websocket.go412
-rw-r--r--libgo/go/websocket/websocket_test.go274
277 files changed, 15442 insertions, 24843 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index 4207948a9cb..b9b249315a6 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-9f2be4fbbf69
+1107a7d3cb07
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index d6578156b8d..3f5bb2ff5b2 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -116,7 +116,6 @@ toolexeclibgo_DATA = \
mime.gox \
net.gox \
os.gox \
- patch.gox \
path.gox \
reflect.gox \
regexp.gox \
@@ -128,8 +127,7 @@ toolexeclibgo_DATA = \
syscall.gox \
testing.gox \
time.gox \
- unicode.gox \
- websocket.gox
+ unicode.gox
toolexeclibgoarchivedir = $(toolexeclibgodir)/archive
@@ -157,40 +155,22 @@ toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \
crypto/aes.gox \
- crypto/bcrypt.gox \
- crypto/blowfish.gox \
- crypto/cast5.gox \
crypto/cipher.gox \
crypto/des.gox \
crypto/dsa.gox \
crypto/ecdsa.gox \
crypto/elliptic.gox \
crypto/hmac.gox \
- crypto/md4.gox \
crypto/md5.gox \
- crypto/ocsp.gox \
- crypto/openpgp.gox \
crypto/rand.gox \
crypto/rc4.gox \
- crypto/ripemd160.gox \
crypto/rsa.gox \
crypto/sha1.gox \
crypto/sha256.gox \
crypto/sha512.gox \
crypto/subtle.gox \
crypto/tls.gox \
- crypto/twofish.gox \
- crypto/x509.gox \
- crypto/xtea.gox
-
-toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
-
-toolexeclibgocryptoopenpgp_DATA = \
- crypto/openpgp/armor.gox \
- crypto/openpgp/elgamal.gox \
- crypto/openpgp/errors.gox \
- crypto/openpgp/packet.gox \
- crypto/openpgp/s2k.gox
+ crypto/x509.gox
toolexeclibgocryptox509dir = $(toolexeclibgocryptodir)/x509
@@ -225,7 +205,6 @@ toolexeclibgoencoding_DATA = \
encoding/base64.gox \
encoding/binary.gox \
encoding/csv.gox \
- encoding/git85.gox \
encoding/gob.gox \
encoding/hex.gox \
encoding/json.gox \
@@ -243,11 +222,10 @@ toolexeclibgoexpdir = $(toolexeclibgodir)/exp
toolexeclibgoexp_DATA = \
exp/ebnf.gox \
+ exp/html.gox \
$(exp_inotify_gox) \
exp/norm.gox \
exp/proxy.gox \
- exp/spdy.gox \
- exp/ssh.gox \
exp/terminal.gox \
exp/types.gox \
exp/utf8string.gox
@@ -317,7 +295,6 @@ toolexeclibgomime_DATA = \
toolexeclibgonetdir = $(toolexeclibgodir)/net
toolexeclibgonet_DATA = \
- net/dict.gox \
net/http.gox \
net/mail.gox \
net/rpc.gox \
@@ -577,16 +554,8 @@ go_hash_files = \
go/hash/hash.go
go_html_files = \
- go/html/const.go \
- go/html/doc.go \
- go/html/doctype.go \
go/html/entity.go \
- go/html/escape.go \
- go/html/foreign.go \
- go/html/node.go \
- go/html/parse.go \
- go/html/render.go \
- go/html/token.go
+ go/html/escape.go
go_image_files = \
go/image/format.go \
@@ -821,12 +790,6 @@ go_os_files = \
go/os/types.go \
signal_unix.go
-go_patch_files = \
- go/patch/apply.go \
- go/patch/git.go \
- go/patch/patch.go \
- go/patch/textdiff.go
-
go_path_files = \
go/path/match.go \
go/path/path.go
@@ -929,13 +892,6 @@ go_unicode_files = \
go/unicode/letter.go \
go/unicode/tables.go
-go_websocket_files = \
- go/websocket/client.go \
- go/websocket/hixie.go \
- go/websocket/hybi.go \
- go/websocket/server.go \
- go/websocket/websocket.go
-
go_archive_tar_files = \
go/archive/tar/common.go \
@@ -959,8 +915,7 @@ go_compress_flate_files = \
go/compress/flate/huffman_code.go \
go/compress/flate/inflate.go \
go/compress/flate/reverse_bits.go \
- go/compress/flate/token.go \
- go/compress/flate/util.go
+ go/compress/flate/token.go
go_compress_gzip_files = \
go/compress/gzip/gzip.go \
@@ -987,15 +942,6 @@ go_crypto_aes_files = \
go/crypto/aes/block.go \
go/crypto/aes/cipher.go \
go/crypto/aes/const.go
-go_crypto_bcrypt_files = \
- go/crypto/bcrypt/base64.go \
- go/crypto/bcrypt/bcrypt.go
-go_crypto_blowfish_files = \
- go/crypto/blowfish/block.go \
- go/crypto/blowfish/const.go \
- go/crypto/blowfish/cipher.go
-go_crypto_cast5_files = \
- go/crypto/cast5/cast5.go
go_crypto_cipher_files = \
go/crypto/cipher/cbc.go \
go/crypto/cipher/cfb.go \
@@ -1017,28 +963,15 @@ go_crypto_elliptic_files = \
go/crypto/elliptic/p224.go
go_crypto_hmac_files = \
go/crypto/hmac/hmac.go
-go_crypto_md4_files = \
- go/crypto/md4/md4.go \
- go/crypto/md4/md4block.go
go_crypto_md5_files = \
go/crypto/md5/md5.go \
go/crypto/md5/md5block.go
-go_crypto_ocsp_files = \
- go/crypto/ocsp/ocsp.go
-go_crypto_openpgp_files = \
- go/crypto/openpgp/canonical_text.go \
- go/crypto/openpgp/keys.go \
- go/crypto/openpgp/read.go \
- go/crypto/openpgp/write.go
go_crypto_rand_files = \
go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go \
go/crypto/rand/util.go
go_crypto_rc4_files = \
go/crypto/rc4/rc4.go
-go_crypto_ripemd160_files = \
- go/crypto/ripemd160/ripemd160.go \
- go/crypto/ripemd160/ripemd160block.go
go_crypto_rsa_files = \
go/crypto/rsa/pkcs1v15.go \
go/crypto/rsa/rsa.go
@@ -1065,40 +998,12 @@ go_crypto_tls_files = \
go/crypto/tls/prf.go \
go/crypto/tls/root_unix.go \
go/crypto/tls/tls.go
-go_crypto_twofish_files = \
- go/crypto/twofish/twofish.go
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
go/crypto/x509/pkcs1.go \
go/crypto/x509/pkcs8.go \
go/crypto/x509/verify.go \
go/crypto/x509/x509.go
-go_crypto_xtea_files = \
- go/crypto/xtea/block.go \
- go/crypto/xtea/cipher.go
-
-go_crypto_openpgp_armor_files = \
- go/crypto/openpgp/armor/armor.go \
- go/crypto/openpgp/armor/encode.go
-go_crypto_openpgp_elgamal_files = \
- go/crypto/openpgp/elgamal/elgamal.go
-go_crypto_openpgp_errors_files = \
- go/crypto/openpgp/errors/errors.go
-go_crypto_openpgp_packet_files = \
- go/crypto/openpgp/packet/compressed.go \
- go/crypto/openpgp/packet/encrypted_key.go \
- go/crypto/openpgp/packet/literal.go \
- go/crypto/openpgp/packet/one_pass_signature.go \
- go/crypto/openpgp/packet/packet.go \
- go/crypto/openpgp/packet/private_key.go \
- go/crypto/openpgp/packet/public_key.go \
- go/crypto/openpgp/packet/reader.go \
- go/crypto/openpgp/packet/signature.go \
- go/crypto/openpgp/packet/symmetric_key_encrypted.go \
- go/crypto/openpgp/packet/symmetrically_encrypted.go \
- go/crypto/openpgp/packet/userid.go
-go_crypto_openpgp_s2k_files = \
- go/crypto/openpgp/s2k/s2k.go
go_crypto_x509_pkix_files = \
go/crypto/x509/pkix/pkix.go
@@ -1147,8 +1052,6 @@ go_encoding_binary_files = \
go_encoding_csv_files = \
go/encoding/csv/reader.go \
go/encoding/csv/writer.go
-go_encoding_git85_files = \
- go/encoding/git85/git.go
go_encoding_gob_files = \
go/encoding/gob/decode.go \
go/encoding/gob/decoder.go \
@@ -1177,6 +1080,17 @@ go_encoding_xml_files = \
go_exp_ebnf_files = \
go/exp/ebnf/ebnf.go \
go/exp/ebnf/parser.go
+go_exp_html_files = \
+ go/exp/html/const.go \
+ go/exp/html/doc.go \
+ go/exp/html/doctype.go \
+ go/exp/html/entity.go \
+ go/exp/html/escape.go \
+ go/exp/html/foreign.go \
+ go/exp/html/node.go \
+ go/exp/html/parse.go \
+ go/exp/html/render.go \
+ go/exp/html/token.go
go_exp_inotify_files = \
go/exp/inotify/inotify_linux.go
go_exp_norm_files = \
@@ -1192,23 +1106,6 @@ go_exp_proxy_files = \
go/exp/proxy/per_host.go \
go/exp/proxy/proxy.go \
go/exp/proxy/socks5.go
-go_exp_spdy_files = \
- go/exp/spdy/read.go \
- go/exp/spdy/types.go \
- go/exp/spdy/write.go
-go_exp_ssh_files = \
- go/exp/ssh/channel.go \
- go/exp/ssh/cipher.go \
- go/exp/ssh/client.go \
- go/exp/ssh/client_auth.go \
- go/exp/ssh/common.go \
- go/exp/ssh/doc.go \
- go/exp/ssh/messages.go \
- go/exp/ssh/server.go \
- go/exp/ssh/server_terminal.go \
- go/exp/ssh/session.go \
- go/exp/ssh/tcpip.go \
- go/exp/ssh/transport.go
go_exp_terminal_files = \
go/exp/terminal/terminal.go \
go/exp/terminal/util.go
@@ -1351,8 +1248,6 @@ go_mime_multipart_files = \
go/mime/multipart/multipart.go \
go/mime/multipart/writer.go
-go_net_dict_files = \
- go/net/dict/dict.go
go_net_http_files = \
go/net/http/chunked.go \
go/net/http/client.go \
@@ -1717,7 +1612,6 @@ libgo_go_objs = \
net/net.lo \
os/exec.lo \
os/os.lo \
- patch/patch.lo \
path/path.lo \
reflect/reflect.lo \
regexp/regexp.lo \
@@ -1728,7 +1622,6 @@ libgo_go_objs = \
sync/sync.lo \
time/time.lo \
unicode/unicode.lo \
- websocket/websocket.lo \
archive/tar.lo \
archive/zip.lo \
compress/bzip2.lo \
@@ -1740,36 +1633,22 @@ libgo_go_objs = \
container/list.lo \
container/ring.lo \
crypto/aes.lo \
- crypto/bcrypt.lo \
- crypto/blowfish.lo \
- crypto/cast5.lo \
crypto/cipher.lo \
crypto/des.lo \
crypto/dsa.lo \
crypto/ecdsa.lo \
crypto/elliptic.lo \
crypto/hmac.lo \
- crypto/md4.lo \
crypto/md5.lo \
- crypto/ocsp.lo \
- crypto/openpgp.lo \
crypto/rand.lo \
crypto/rc4.lo \
- crypto/ripemd160.lo \
crypto/rsa.lo \
crypto/sha1.lo \
crypto/sha256.lo \
crypto/sha512.lo \
crypto/subtle.lo \
crypto/tls.lo \
- crypto/twofish.lo \
crypto/x509.lo \
- crypto/xtea.lo \
- crypto/openpgp/armor.lo \
- crypto/openpgp/elgamal.lo \
- crypto/openpgp/errors.lo \
- crypto/openpgp/packet.lo \
- crypto/openpgp/s2k.lo \
crypto/x509/pkix.lo \
database/sql.lo \
database/sql/driver.lo \
@@ -1784,17 +1663,15 @@ libgo_go_objs = \
encoding/base64.lo \
encoding/binary.lo \
encoding/csv.lo \
- encoding/git85.lo \
encoding/gob.lo \
encoding/hex.lo \
encoding/json.lo \
encoding/pem.lo \
encoding/xml.lo \
exp/ebnf.lo \
+ exp/html.lo \
exp/norm.lo \
exp/proxy.lo \
- exp/spdy.lo \
- exp/ssh.lo \
exp/terminal.lo \
exp/types.lo \
exp/utf8string.lo \
@@ -1831,7 +1708,6 @@ libgo_go_objs = \
math/rand.lo \
mime/mime.lo \
mime/multipart.lo \
- net/dict.lo \
net/http.lo \
net/mail.lo \
net/rpc.lo \
@@ -1946,7 +1822,6 @@ CHECK_DEPS = libgo.la libgobegin.a \
$(toolexeclibgocompress_DATA) \
$(toolexeclibgocontainer_DATA) \
$(toolexeclibgocrypto_DATA) \
- $(toolexeclibgocryptoopenpgp_DATA) \
$(toolexeclibgodebug_DATA) \
$(toolexeclibgoencoding_DATA) \
$(toolexeclibgoexp_DATA) \
@@ -2120,15 +1995,6 @@ signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
$(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
mv -f $@.tmp $@
-@go_include@ patch/patch.lo.dep
-patch/patch.lo.dep: $(go_patch_files)
- $(BUILDDEPS)
-patch/patch.lo: $(go_patch_files)
- $(BUILDPACKAGE)
-patch/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: patch/check
-
@go_include@ path/path.lo.dep
path/path.lo.dep: $(go_path_files)
$(BUILDDEPS)
@@ -2238,15 +2104,6 @@ unicode/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: unicode/check
-@go_include@ websocket/websocket.lo.dep
-websocket/websocket.lo.dep: $(go_websocket_files)
- $(BUILDDEPS)
-websocket/websocket.lo: $(go_websocket_files)
- $(BUILDPACKAGE)
-websocket/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: websocket/check
-
@go_include@ archive/tar.lo.dep
archive/tar.lo.dep: $(go_archive_tar_files)
$(BUILDDEPS)
@@ -2357,36 +2214,6 @@ crypto/aes/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/aes/check
-@go_include@ crypto/bcrypt.lo.dep
-crypto/bcrypt.lo.dep: $(go_crypto_bcrypt_files)
- $(BUILDDEPS)
-crypto/bcrypt.lo: $(go_crypto_bcrypt_files)
- $(BUILDPACKAGE)
-crypto/bcrypt/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/bcrypt
- @$(CHECK)
-.PHONY: crypto/bcrypt/check
-
-@go_include@ crypto/blowfish.lo.dep
-crypto/blowfish.lo.dep: $(go_crypto_blowfish_files)
- $(BUILDDEPS)
-crypto/blowfish.lo: $(go_crypto_blowfish_files)
- $(BUILDPACKAGE)
-crypto/blowfish/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/blowfish
- @$(CHECK)
-.PHONY: crypto/blowfish/check
-
-@go_include@ crypto/cast5.lo.dep
-crypto/cast5.lo.dep: $(go_crypto_cast5_files)
- $(BUILDDEPS)
-crypto/cast5.lo: $(go_crypto_cast5_files)
- $(BUILDPACKAGE)
-crypto/cast5/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/cast5
- @$(CHECK)
-.PHONY: crypto/cast5/check
-
@go_include@ crypto/cipher.lo.dep
crypto/cipher.lo.dep: $(go_crypto_cipher_files)
$(BUILDDEPS)
@@ -2447,16 +2274,6 @@ crypto/hmac/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/hmac/check
-@go_include@ crypto/md4.lo.dep
-crypto/md4.lo.dep: $(go_crypto_md4_files)
- $(BUILDDEPS)
-crypto/md4.lo: $(go_crypto_md4_files)
- $(BUILDPACKAGE)
-crypto/md4/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/md4
- @$(CHECK)
-.PHONY: crypto/md4/check
-
@go_include@ crypto/md5.lo.dep
crypto/md5.lo.dep: $(go_crypto_md5_files)
$(BUILDDEPS)
@@ -2467,26 +2284,6 @@ crypto/md5/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/md5/check
-@go_include@ crypto/ocsp.lo.dep
-crypto/ocsp.lo.dep: $(go_crypto_ocsp_files)
- $(BUILDDEPS)
-crypto/ocsp.lo: $(go_crypto_ocsp_files)
- $(BUILDPACKAGE)
-crypto/ocsp/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/ocsp
- @$(CHECK)
-.PHONY: crypto/ocsp/check
-
-@go_include@ crypto/openpgp.lo.dep
-crypto/openpgp.lo.dep: $(go_crypto_openpgp_files)
- $(BUILDDEPS)
-crypto/openpgp.lo: $(go_crypto_openpgp_files)
- $(BUILDPACKAGE)
-crypto/openpgp/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp
- @$(CHECK)
-.PHONY: crypto/openpgp/check
-
@go_include@ crypto/rand.lo.dep
crypto/rand.lo.dep: $(go_crypto_rand_files)
$(BUILDDEPS)
@@ -2507,16 +2304,6 @@ crypto/rc4/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/rc4/check
-@go_include@ crypto/ripemd160.lo.dep
-crypto/ripemd160.lo.dep: $(go_crypto_ripemd160_files)
- $(BUILDDEPS)
-crypto/ripemd160.lo: $(go_crypto_ripemd160_files)
- $(BUILDPACKAGE)
-crypto/ripemd160/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/ripemd160
- @$(CHECK)
-.PHONY: crypto/ripemd160/check
-
@go_include@ crypto/rsa.lo.dep
crypto/rsa.lo.dep: $(go_crypto_rsa_files)
$(BUILDDEPS)
@@ -2577,16 +2364,6 @@ crypto/tls/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/tls/check
-@go_include@ crypto/twofish.lo.dep
-crypto/twofish.lo.dep: $(go_crypto_twofish_files)
- $(BUILDDEPS)
-crypto/twofish.lo: $(go_crypto_twofish_files)
- $(BUILDPACKAGE)
-crypto/twofish/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/twofish
- @$(CHECK)
-.PHONY: crypto/twofish/check
-
@go_include@ crypto/x509.lo.dep
crypto/x509.lo.dep: $(go_crypto_x509_files)
$(BUILDDEPS)
@@ -2597,66 +2374,6 @@ crypto/x509/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/x509/check
-@go_include@ crypto/xtea.lo.dep
-crypto/xtea.lo.dep: $(go_crypto_xtea_files)
- $(BUILDDEPS)
-crypto/xtea.lo: $(go_crypto_xtea_files)
- $(BUILDPACKAGE)
-crypto/xtea/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/xtea
- @$(CHECK)
-.PHONY: crypto/xtea/check
-
-@go_include@ crypto/openpgp/armor.lo.dep
-crypto/openpgp/armor.lo.dep: $(go_crypto_openpgp_armor_files)
- $(BUILDDEPS)
-crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files)
- $(BUILDPACKAGE)
-crypto/openpgp/armor/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/armor
- @$(CHECK)
-.PHONY: crypto/openpgp/armor/check
-
-@go_include@ crypto/openpgp/elgamal.lo.dep
-crypto/openpgp/elgamal.lo.dep: $(go_crypto_openpgp_elgamal_files)
- $(BUILDDEPS)
-crypto/openpgp/elgamal.lo: $(go_crypto_openpgp_elgamal_files)
- $(BUILDPACKAGE)
-crypto/openpgp/elgamal/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/elgamal
- @$(CHECK)
-.PHONY: crypto/openpgp/elgamal/check
-
-@go_include@ crypto/openpgp/errors.lo.dep
-crypto/openpgp/errors.lo.dep: $(go_crypto_openpgp_errors_files)
- $(BUILDDEPS)
-crypto/openpgp/errors.lo: $(go_crypto_openpgp_errors_files)
- $(BUILDPACKAGE)
-crypto/openpgp/errors/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/errors
- @$(CHECK)
-.PHONY: crypto/openpgp/errors/check
-
-@go_include@ crypto/openpgp/packet.lo.dep
-crypto/openpgp/packet.lo.dep: $(go_crypto_openpgp_packet_files)
- $(BUILDDEPS)
-crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files)
- $(BUILDPACKAGE)
-crypto/openpgp/packet/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/packet
- @$(CHECK)
-.PHONY: crypto/openpgp/packet/check
-
-@go_include@ crypto/openpgp/s2k.lo.dep
-crypto/openpgp/s2k.lo.dep: $(go_crypto_openpgp_s2k_files)
- $(BUILDDEPS)
-crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files)
- $(BUILDPACKAGE)
-crypto/openpgp/s2k/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/s2k
- @$(CHECK)
-.PHONY: crypto/openpgp/s2k/check
-
@go_include@ crypto/x509/pkix.lo.dep
crypto/x509/pkix.lo.dep: $(go_crypto_x509_pkix_files)
$(BUILDDEPS)
@@ -2797,16 +2514,6 @@ encoding/csv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: encoding/csv/check
-@go_include@ encoding/git85.lo.dep
-encoding/git85.lo.dep: $(go_encoding_git85_files)
- $(BUILDDEPS)
-encoding/git85.lo: $(go_encoding_git85_files)
- $(BUILDPACKAGE)
-encoding/git85/check: $(CHECK_DEPS)
- @$(MKDIR_P) encoding/git85
- @$(CHECK)
-.PHONY: encoding/git85/check
-
@go_include@ encoding/gob.lo.dep
encoding/gob.lo.dep: $(go_encoding_gob_files)
$(BUILDDEPS)
@@ -2867,6 +2574,16 @@ exp/ebnf/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/ebnf/check
+@go_include@ exp/html.lo.dep
+exp/html.lo.dep: $(go_exp_html_files)
+ $(BUILDDEPS)
+exp/html.lo: $(go_exp_html_files)
+ $(BUILDPACKAGE)
+exp/html/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/html
+ @$(CHECK)
+.PHONY: exp/html/check
+
@go_include@ exp/norm.lo.dep
exp/norm.lo.dep: $(go_exp_norm_files)
$(BUILDDEPS)
@@ -2887,26 +2604,6 @@ exp/proxy/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/proxy/check
-@go_include@ exp/spdy.lo.dep
-exp/spdy.lo.dep: $(go_exp_spdy_files)
- $(BUILDDEPS)
-exp/spdy.lo: $(go_exp_spdy_files)
- $(BUILDPACKAGE)
-exp/spdy/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/spdy
- @$(CHECK)
-.PHONY: exp/spdy/check
-
-@go_include@ exp/ssh.lo.dep
-exp/ssh.lo.dep: $(go_exp_ssh_files)
- $(BUILDDEPS)
-exp/ssh.lo: $(go_exp_ssh_files)
- $(BUILDPACKAGE)
-exp/ssh/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/ssh
- @$(CHECK)
-.PHONY: exp/ssh/check
-
@go_include@ exp/terminal.lo.dep
exp/terminal.lo.dep: $(go_exp_terminal_files)
$(BUILDDEPS)
@@ -3218,12 +2915,6 @@ mime/multipart/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/multipart/check
-@go_include@ net/dict.lo.dep
-net/dict.lo.dep: $(go_net_dict_files)
- $(BUILDDEPS)
-net/dict.lo: $(go_net_dict_files)
- $(BUILDPACKAGE)
-
@go_include@ net/http.lo.dep
net/http.lo.dep: $(go_net_http_files)
$(BUILDDEPS)
@@ -3582,8 +3273,6 @@ net.gox: net/net.lo
$(BUILDGOX)
os.gox: os/os.lo
$(BUILDGOX)
-patch.gox: patch/patch.lo
- $(BUILDGOX)
path.gox: path/path.lo
$(BUILDGOX)
reflect.gox: reflect/reflect.lo
@@ -3608,8 +3297,6 @@ time.gox: time/time.lo
$(BUILDGOX)
unicode.gox: unicode/unicode.lo
$(BUILDGOX)
-websocket.gox: websocket/websocket.lo
- $(BUILDGOX)
archive/tar.gox: archive/tar.lo
$(BUILDGOX)
@@ -3636,12 +3323,6 @@ container/ring.gox: container/ring.lo
crypto/aes.gox: crypto/aes.lo
$(BUILDGOX)
-crypto/bcrypt.gox: crypto/bcrypt.lo
- $(BUILDGOX)
-crypto/blowfish.gox: crypto/blowfish.lo
- $(BUILDGOX)
-crypto/cast5.gox: crypto/cast5.lo
- $(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX)
crypto/des.gox: crypto/des.lo
@@ -3654,20 +3335,12 @@ crypto/elliptic.gox: crypto/elliptic.lo
$(BUILDGOX)
crypto/hmac.gox: crypto/hmac.lo
$(BUILDGOX)
-crypto/md4.gox: crypto/md4.lo
- $(BUILDGOX)
crypto/md5.gox: crypto/md5.lo
$(BUILDGOX)
-crypto/ocsp.gox: crypto/ocsp.lo
- $(BUILDGOX)
-crypto/openpgp.gox: crypto/openpgp.lo
- $(BUILDGOX)
crypto/rand.gox: crypto/rand.lo
$(BUILDGOX)
crypto/rc4.gox: crypto/rc4.lo
$(BUILDGOX)
-crypto/ripemd160.gox: crypto/ripemd160.lo
- $(BUILDGOX)
crypto/rsa.gox: crypto/rsa.lo
$(BUILDGOX)
crypto/sha1.gox: crypto/sha1.lo
@@ -3680,23 +3353,8 @@ crypto/subtle.gox: crypto/subtle.lo
$(BUILDGOX)
crypto/tls.gox: crypto/tls.lo
$(BUILDGOX)
-crypto/twofish.gox: crypto/twofish.lo
- $(BUILDGOX)
crypto/x509.gox: crypto/x509.lo
$(BUILDGOX)
-crypto/xtea.gox: crypto/xtea.lo
- $(BUILDGOX)
-
-crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
- $(BUILDGOX)
-crypto/openpgp/elgamal.gox: crypto/openpgp/elgamal.lo
- $(BUILDGOX)
-crypto/openpgp/errors.gox: crypto/openpgp/errors.lo
- $(BUILDGOX)
-crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
- $(BUILDGOX)
-crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
- $(BUILDGOX)
crypto/x509/pkix.gox: crypto/x509/pkix.lo
$(BUILDGOX)
@@ -3730,8 +3388,6 @@ encoding/binary.gox: encoding/binary.lo
$(BUILDGOX)
encoding/csv.gox: encoding/csv.lo
$(BUILDGOX)
-encoding/git85.gox: encoding/git85.lo
- $(BUILDGOX)
encoding/gob.gox: encoding/gob.lo
$(BUILDGOX)
encoding/hex.gox: encoding/hex.lo
@@ -3745,16 +3401,14 @@ encoding/xml.gox: encoding/xml.lo
exp/ebnf.gox: exp/ebnf.lo
$(BUILDGOX)
+exp/html.gox: exp/html.lo
+ $(BUILDGOX)
exp/inotify.gox: exp/inotify.lo
$(BUILDGOX)
exp/norm.gox: exp/norm.lo
$(BUILDGOX)
exp/proxy.gox: exp/proxy.lo
$(BUILDGOX)
-exp/spdy.gox: exp/spdy.lo
- $(BUILDGOX)
-exp/ssh.gox: exp/ssh.lo
- $(BUILDGOX)
exp/terminal.gox: exp/terminal.lo
$(BUILDGOX)
exp/types.gox: exp/types.lo
@@ -3823,8 +3477,6 @@ math/rand.gox: math/rand.lo
mime/multipart.gox: mime/multipart.lo
$(BUILDGOX)
-net/dict.gox: net/dict.lo
- $(BUILDGOX)
net/http.gox: net/http.lo
$(BUILDGOX)
net/mail.gox: net/mail.lo
@@ -3923,7 +3575,6 @@ TEST_PACKAGES = \
mime/check \
net/check \
os/check \
- patch/check \
path/check \
reflect/check \
regexp/check \
@@ -3934,7 +3585,6 @@ TEST_PACKAGES = \
sync/check \
time/check \
unicode/check \
- websocket/check \
archive/tar/check \
archive/zip/check \
compress/bzip2/check \
@@ -3946,35 +3596,22 @@ TEST_PACKAGES = \
container/list/check \
container/ring/check \
crypto/aes/check \
- crypto/bcrypt/check \
- crypto/blowfish/check \
- crypto/cast5/check \
crypto/cipher/check \
crypto/des/check \
crypto/dsa/check \
crypto/ecdsa/check \
crypto/elliptic/check \
crypto/hmac/check \
- crypto/md4/check \
crypto/md5/check \
- crypto/ocsp/check \
- crypto/openpgp/check \
crypto/rand/check \
crypto/rc4/check \
- crypto/ripemd160/check \
crypto/rsa/check \
crypto/sha1/check \
crypto/sha256/check \
crypto/sha512/check \
crypto/subtle/check \
crypto/tls/check \
- crypto/twofish/check \
crypto/x509/check \
- crypto/xtea/check \
- crypto/openpgp/armor/check \
- crypto/openpgp/elgamal/check \
- crypto/openpgp/packet/check \
- crypto/openpgp/s2k/check \
database/sql/check \
database/sql/driver/check \
debug/dwarf/check \
@@ -3987,18 +3624,16 @@ TEST_PACKAGES = \
encoding/base64/check \
encoding/binary/check \
encoding/csv/check \
- encoding/git85/check \
encoding/gob/check \
encoding/hex/check \
encoding/json/check \
encoding/pem/check \
encoding/xml/check \
exp/ebnf/check \
+ exp/html/check \
$(exp_inotify_check) \
exp/norm/check \
exp/proxy/check \
- exp/spdy/check \
- exp/ssh/check \
exp/terminal/check \
exp/utf8string/check \
html/template/check \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 6e0cea813f8..4aebb2d6fd7 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -97,7 +97,6 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgocompressdir)" \
"$(DESTDIR)$(toolexeclibgocontainerdir)" \
"$(DESTDIR)$(toolexeclibgocryptodir)" \
- "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" \
"$(DESTDIR)$(toolexeclibgocryptox509dir)" \
"$(DESTDIR)$(toolexeclibgodatabasedir)" \
"$(DESTDIR)$(toolexeclibgodatabasesqldir)" \
@@ -138,31 +137,24 @@ am__DEPENDENCIES_2 = bufio/bufio.lo bytes/bytes.lo bytes/index.lo \
crypto/crypto.lo errors/errors.lo expvar/expvar.lo \
flag/flag.lo fmt/fmt.lo hash/hash.lo html/html.lo \
image/image.lo io/io.lo log/log.lo math/math.lo net/net.lo \
- os/exec.lo os/os.lo patch/patch.lo path/path.lo \
- reflect/reflect.lo regexp/regexp.lo runtime/runtime.lo \
- sort/sort.lo strconv/strconv.lo strings/strings.lo \
- sync/sync.lo time/time.lo unicode/unicode.lo \
- websocket/websocket.lo archive/tar.lo archive/zip.lo \
+ os/exec.lo os/os.lo path/path.lo reflect/reflect.lo \
+ regexp/regexp.lo runtime/runtime.lo sort/sort.lo \
+ strconv/strconv.lo strings/strings.lo sync/sync.lo \
+ time/time.lo unicode/unicode.lo archive/tar.lo archive/zip.lo \
compress/bzip2.lo compress/flate.lo compress/gzip.lo \
compress/lzw.lo compress/zlib.lo container/heap.lo \
container/list.lo container/ring.lo crypto/aes.lo \
- crypto/bcrypt.lo crypto/blowfish.lo crypto/cast5.lo \
crypto/cipher.lo crypto/des.lo crypto/dsa.lo crypto/ecdsa.lo \
- crypto/elliptic.lo crypto/hmac.lo crypto/md4.lo crypto/md5.lo \
- crypto/ocsp.lo crypto/openpgp.lo crypto/rand.lo crypto/rc4.lo \
- crypto/ripemd160.lo crypto/rsa.lo crypto/sha1.lo \
- crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \
- crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \
- crypto/openpgp/armor.lo crypto/openpgp/elgamal.lo \
- crypto/openpgp/errors.lo crypto/openpgp/packet.lo \
- crypto/openpgp/s2k.lo crypto/x509/pkix.lo database/sql.lo \
- database/sql/driver.lo debug/dwarf.lo debug/elf.lo \
- debug/gosym.lo debug/macho.lo debug/pe.lo encoding/ascii85.lo \
- encoding/asn1.lo encoding/base32.lo encoding/base64.lo \
- encoding/binary.lo encoding/csv.lo encoding/git85.lo \
- encoding/gob.lo encoding/hex.lo encoding/json.lo \
- encoding/pem.lo encoding/xml.lo exp/ebnf.lo exp/norm.lo \
- exp/proxy.lo exp/spdy.lo exp/ssh.lo exp/terminal.lo \
+ crypto/elliptic.lo crypto/hmac.lo crypto/md5.lo crypto/rand.lo \
+ crypto/rc4.lo crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo \
+ crypto/sha512.lo crypto/subtle.lo crypto/tls.lo crypto/x509.lo \
+ crypto/x509/pkix.lo database/sql.lo database/sql/driver.lo \
+ debug/dwarf.lo debug/elf.lo debug/gosym.lo debug/macho.lo \
+ debug/pe.lo encoding/ascii85.lo encoding/asn1.lo \
+ encoding/base32.lo encoding/base64.lo encoding/binary.lo \
+ encoding/csv.lo encoding/gob.lo encoding/hex.lo \
+ encoding/json.lo encoding/pem.lo encoding/xml.lo exp/ebnf.lo \
+ exp/html.lo exp/norm.lo exp/proxy.lo exp/terminal.lo \
exp/types.lo exp/utf8string.lo html/template.lo go/ast.lo \
go/build.lo go/doc.lo go/parser.lo go/printer.lo go/scanner.lo \
go/token.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
@@ -172,7 +164,7 @@ am__DEPENDENCIES_2 = bufio/bufio.lo bytes/bytes.lo bytes/index.lo \
image/jpeg.lo image/png.lo image/tiff.lo index/suffixarray.lo \
io/ioutil.lo log/syslog.lo log/syslog/syslog_c.lo math/big.lo \
math/cmplx.lo math/rand.lo mime/mime.lo mime/multipart.lo \
- net/dict.lo net/http.lo net/mail.lo net/rpc.lo net/smtp.lo \
+ net/http.lo net/mail.lo net/rpc.lo net/smtp.lo \
net/textproto.lo net/url.lo old/netchan.lo old/regexp.lo \
old/template.lo $(am__DEPENDENCIES_1) os/user.lo os/signal.lo \
path/filepath.lo regexp/syntax.lo net/rpc/jsonrpc.lo \
@@ -289,21 +281,21 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
ps-recursive uninstall-recursive
DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \
- $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptoopenpgp_DATA) \
- $(toolexeclibgocryptox509_DATA) $(toolexeclibgodatabase_DATA) \
- $(toolexeclibgodatabasesql_DATA) $(toolexeclibgodebug_DATA) \
- $(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \
- $(toolexeclibgogo_DATA) $(toolexeclibgohash_DATA) \
- $(toolexeclibgohtml_DATA) $(toolexeclibgoimage_DATA) \
- $(toolexeclibgoindex_DATA) $(toolexeclibgoio_DATA) \
- $(toolexeclibgolog_DATA) $(toolexeclibgomath_DATA) \
- $(toolexeclibgomime_DATA) $(toolexeclibgonet_DATA) \
- $(toolexeclibgonethttp_DATA) $(toolexeclibgonetrpc_DATA) \
- $(toolexeclibgoold_DATA) $(toolexeclibgoos_DATA) \
- $(toolexeclibgopath_DATA) $(toolexeclibgoregexp_DATA) \
- $(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \
- $(toolexeclibgotesting_DATA) $(toolexeclibgotext_DATA) \
- $(toolexeclibgotexttemplate_DATA) $(toolexeclibgounicode_DATA)
+ $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptox509_DATA) \
+ $(toolexeclibgodatabase_DATA) $(toolexeclibgodatabasesql_DATA) \
+ $(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \
+ $(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \
+ $(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \
+ $(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
+ $(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \
+ $(toolexeclibgomath_DATA) $(toolexeclibgomime_DATA) \
+ $(toolexeclibgonet_DATA) $(toolexeclibgonethttp_DATA) \
+ $(toolexeclibgonetrpc_DATA) $(toolexeclibgoold_DATA) \
+ $(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \
+ $(toolexeclibgoregexp_DATA) $(toolexeclibgoruntime_DATA) \
+ $(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \
+ $(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \
+ $(toolexeclibgounicode_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -587,7 +579,6 @@ toolexeclibgo_DATA = \
mime.gox \
net.gox \
os.gox \
- patch.gox \
path.gox \
reflect.gox \
regexp.gox \
@@ -599,8 +590,7 @@ toolexeclibgo_DATA = \
syscall.gox \
testing.gox \
time.gox \
- unicode.gox \
- websocket.gox
+ unicode.gox
toolexeclibgoarchivedir = $(toolexeclibgodir)/archive
toolexeclibgoarchive_DATA = \
@@ -624,39 +614,22 @@ toolexeclibgocontainer_DATA = \
toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \
crypto/aes.gox \
- crypto/bcrypt.gox \
- crypto/blowfish.gox \
- crypto/cast5.gox \
crypto/cipher.gox \
crypto/des.gox \
crypto/dsa.gox \
crypto/ecdsa.gox \
crypto/elliptic.gox \
crypto/hmac.gox \
- crypto/md4.gox \
crypto/md5.gox \
- crypto/ocsp.gox \
- crypto/openpgp.gox \
crypto/rand.gox \
crypto/rc4.gox \
- crypto/ripemd160.gox \
crypto/rsa.gox \
crypto/sha1.gox \
crypto/sha256.gox \
crypto/sha512.gox \
crypto/subtle.gox \
crypto/tls.gox \
- crypto/twofish.gox \
- crypto/x509.gox \
- crypto/xtea.gox
-
-toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
-toolexeclibgocryptoopenpgp_DATA = \
- crypto/openpgp/armor.gox \
- crypto/openpgp/elgamal.gox \
- crypto/openpgp/errors.gox \
- crypto/openpgp/packet.gox \
- crypto/openpgp/s2k.gox
+ crypto/x509.gox
toolexeclibgocryptox509dir = $(toolexeclibgocryptodir)/x509
toolexeclibgocryptox509_DATA = \
@@ -686,7 +659,6 @@ toolexeclibgoencoding_DATA = \
encoding/base64.gox \
encoding/binary.gox \
encoding/csv.gox \
- encoding/git85.gox \
encoding/gob.gox \
encoding/hex.gox \
encoding/json.gox \
@@ -700,11 +672,10 @@ toolexeclibgoencoding_DATA = \
toolexeclibgoexpdir = $(toolexeclibgodir)/exp
toolexeclibgoexp_DATA = \
exp/ebnf.gox \
+ exp/html.gox \
$(exp_inotify_gox) \
exp/norm.gox \
exp/proxy.gox \
- exp/spdy.gox \
- exp/ssh.gox \
exp/terminal.gox \
exp/types.gox \
exp/utf8string.gox
@@ -764,7 +735,6 @@ toolexeclibgomime_DATA = \
toolexeclibgonetdir = $(toolexeclibgodir)/net
toolexeclibgonet_DATA = \
- net/dict.gox \
net/http.gox \
net/mail.gox \
net/rpc.gox \
@@ -963,16 +933,8 @@ go_hash_files = \
go/hash/hash.go
go_html_files = \
- go/html/const.go \
- go/html/doc.go \
- go/html/doctype.go \
go/html/entity.go \
- go/html/escape.go \
- go/html/foreign.go \
- go/html/node.go \
- go/html/parse.go \
- go/html/render.go \
- go/html/token.go
+ go/html/escape.go
go_image_files = \
go/image/format.go \
@@ -1146,12 +1108,6 @@ go_os_files = \
go/os/types.go \
signal_unix.go
-go_patch_files = \
- go/patch/apply.go \
- go/patch/git.go \
- go/patch/patch.go \
- go/patch/textdiff.go
-
go_path_files = \
go/path/match.go \
go/path/path.go
@@ -1237,13 +1193,6 @@ go_unicode_files = \
go/unicode/letter.go \
go/unicode/tables.go
-go_websocket_files = \
- go/websocket/client.go \
- go/websocket/hixie.go \
- go/websocket/hybi.go \
- go/websocket/server.go \
- go/websocket/websocket.go
-
go_archive_tar_files = \
go/archive/tar/common.go \
go/archive/tar/reader.go \
@@ -1266,8 +1215,7 @@ go_compress_flate_files = \
go/compress/flate/huffman_code.go \
go/compress/flate/inflate.go \
go/compress/flate/reverse_bits.go \
- go/compress/flate/token.go \
- go/compress/flate/util.go
+ go/compress/flate/token.go
go_compress_gzip_files = \
go/compress/gzip/gzip.go \
@@ -1295,18 +1243,6 @@ go_crypto_aes_files = \
go/crypto/aes/cipher.go \
go/crypto/aes/const.go
-go_crypto_bcrypt_files = \
- go/crypto/bcrypt/base64.go \
- go/crypto/bcrypt/bcrypt.go
-
-go_crypto_blowfish_files = \
- go/crypto/blowfish/block.go \
- go/crypto/blowfish/const.go \
- go/crypto/blowfish/cipher.go
-
-go_crypto_cast5_files = \
- go/crypto/cast5/cast5.go
-
go_crypto_cipher_files = \
go/crypto/cipher/cbc.go \
go/crypto/cipher/cfb.go \
@@ -1334,23 +1270,10 @@ go_crypto_elliptic_files = \
go_crypto_hmac_files = \
go/crypto/hmac/hmac.go
-go_crypto_md4_files = \
- go/crypto/md4/md4.go \
- go/crypto/md4/md4block.go
-
go_crypto_md5_files = \
go/crypto/md5/md5.go \
go/crypto/md5/md5block.go
-go_crypto_ocsp_files = \
- go/crypto/ocsp/ocsp.go
-
-go_crypto_openpgp_files = \
- go/crypto/openpgp/canonical_text.go \
- go/crypto/openpgp/keys.go \
- go/crypto/openpgp/read.go \
- go/crypto/openpgp/write.go
-
go_crypto_rand_files = \
go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go \
@@ -1359,10 +1282,6 @@ go_crypto_rand_files = \
go_crypto_rc4_files = \
go/crypto/rc4/rc4.go
-go_crypto_ripemd160_files = \
- go/crypto/ripemd160/ripemd160.go \
- go/crypto/ripemd160/ripemd160block.go
-
go_crypto_rsa_files = \
go/crypto/rsa/pkcs1v15.go \
go/crypto/rsa/rsa.go
@@ -1395,9 +1314,6 @@ go_crypto_tls_files = \
go/crypto/tls/root_unix.go \
go/crypto/tls/tls.go
-go_crypto_twofish_files = \
- go/crypto/twofish/twofish.go
-
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
go/crypto/x509/pkcs1.go \
@@ -1405,37 +1321,6 @@ go_crypto_x509_files = \
go/crypto/x509/verify.go \
go/crypto/x509/x509.go
-go_crypto_xtea_files = \
- go/crypto/xtea/block.go \
- go/crypto/xtea/cipher.go
-
-go_crypto_openpgp_armor_files = \
- go/crypto/openpgp/armor/armor.go \
- go/crypto/openpgp/armor/encode.go
-
-go_crypto_openpgp_elgamal_files = \
- go/crypto/openpgp/elgamal/elgamal.go
-
-go_crypto_openpgp_errors_files = \
- go/crypto/openpgp/errors/errors.go
-
-go_crypto_openpgp_packet_files = \
- go/crypto/openpgp/packet/compressed.go \
- go/crypto/openpgp/packet/encrypted_key.go \
- go/crypto/openpgp/packet/literal.go \
- go/crypto/openpgp/packet/one_pass_signature.go \
- go/crypto/openpgp/packet/packet.go \
- go/crypto/openpgp/packet/private_key.go \
- go/crypto/openpgp/packet/public_key.go \
- go/crypto/openpgp/packet/reader.go \
- go/crypto/openpgp/packet/signature.go \
- go/crypto/openpgp/packet/symmetric_key_encrypted.go \
- go/crypto/openpgp/packet/symmetrically_encrypted.go \
- go/crypto/openpgp/packet/userid.go
-
-go_crypto_openpgp_s2k_files = \
- go/crypto/openpgp/s2k/s2k.go
-
go_crypto_x509_pkix_files = \
go/crypto/x509/pkix/pkix.go
@@ -1493,9 +1378,6 @@ go_encoding_csv_files = \
go/encoding/csv/reader.go \
go/encoding/csv/writer.go
-go_encoding_git85_files = \
- go/encoding/git85/git.go
-
go_encoding_gob_files = \
go/encoding/gob/decode.go \
go/encoding/gob/decoder.go \
@@ -1529,6 +1411,18 @@ go_exp_ebnf_files = \
go/exp/ebnf/ebnf.go \
go/exp/ebnf/parser.go
+go_exp_html_files = \
+ go/exp/html/const.go \
+ go/exp/html/doc.go \
+ go/exp/html/doctype.go \
+ go/exp/html/entity.go \
+ go/exp/html/escape.go \
+ go/exp/html/foreign.go \
+ go/exp/html/node.go \
+ go/exp/html/parse.go \
+ go/exp/html/render.go \
+ go/exp/html/token.go
+
go_exp_inotify_files = \
go/exp/inotify/inotify_linux.go
@@ -1547,25 +1441,6 @@ go_exp_proxy_files = \
go/exp/proxy/proxy.go \
go/exp/proxy/socks5.go
-go_exp_spdy_files = \
- go/exp/spdy/read.go \
- go/exp/spdy/types.go \
- go/exp/spdy/write.go
-
-go_exp_ssh_files = \
- go/exp/ssh/channel.go \
- go/exp/ssh/cipher.go \
- go/exp/ssh/client.go \
- go/exp/ssh/client_auth.go \
- go/exp/ssh/common.go \
- go/exp/ssh/doc.go \
- go/exp/ssh/messages.go \
- go/exp/ssh/server.go \
- go/exp/ssh/server_terminal.go \
- go/exp/ssh/session.go \
- go/exp/ssh/tcpip.go \
- go/exp/ssh/transport.go
-
go_exp_terminal_files = \
go/exp/terminal/terminal.go \
go/exp/terminal/util.go
@@ -1721,9 +1596,6 @@ go_mime_multipart_files = \
go/mime/multipart/multipart.go \
go/mime/multipart/writer.go
-go_net_dict_files = \
- go/net/dict/dict.go
-
go_net_http_files = \
go/net/http/chunked.go \
go/net/http/client.go \
@@ -1988,7 +1860,6 @@ libgo_go_objs = \
net/net.lo \
os/exec.lo \
os/os.lo \
- patch/patch.lo \
path/path.lo \
reflect/reflect.lo \
regexp/regexp.lo \
@@ -1999,7 +1870,6 @@ libgo_go_objs = \
sync/sync.lo \
time/time.lo \
unicode/unicode.lo \
- websocket/websocket.lo \
archive/tar.lo \
archive/zip.lo \
compress/bzip2.lo \
@@ -2011,36 +1881,22 @@ libgo_go_objs = \
container/list.lo \
container/ring.lo \
crypto/aes.lo \
- crypto/bcrypt.lo \
- crypto/blowfish.lo \
- crypto/cast5.lo \
crypto/cipher.lo \
crypto/des.lo \
crypto/dsa.lo \
crypto/ecdsa.lo \
crypto/elliptic.lo \
crypto/hmac.lo \
- crypto/md4.lo \
crypto/md5.lo \
- crypto/ocsp.lo \
- crypto/openpgp.lo \
crypto/rand.lo \
crypto/rc4.lo \
- crypto/ripemd160.lo \
crypto/rsa.lo \
crypto/sha1.lo \
crypto/sha256.lo \
crypto/sha512.lo \
crypto/subtle.lo \
crypto/tls.lo \
- crypto/twofish.lo \
crypto/x509.lo \
- crypto/xtea.lo \
- crypto/openpgp/armor.lo \
- crypto/openpgp/elgamal.lo \
- crypto/openpgp/errors.lo \
- crypto/openpgp/packet.lo \
- crypto/openpgp/s2k.lo \
crypto/x509/pkix.lo \
database/sql.lo \
database/sql/driver.lo \
@@ -2055,17 +1911,15 @@ libgo_go_objs = \
encoding/base64.lo \
encoding/binary.lo \
encoding/csv.lo \
- encoding/git85.lo \
encoding/gob.lo \
encoding/hex.lo \
encoding/json.lo \
encoding/pem.lo \
encoding/xml.lo \
exp/ebnf.lo \
+ exp/html.lo \
exp/norm.lo \
exp/proxy.lo \
- exp/spdy.lo \
- exp/ssh.lo \
exp/terminal.lo \
exp/types.lo \
exp/utf8string.lo \
@@ -2102,7 +1956,6 @@ libgo_go_objs = \
math/rand.lo \
mime/mime.lo \
mime/multipart.lo \
- net/dict.lo \
net/http.lo \
net/mail.lo \
net/rpc.lo \
@@ -2211,7 +2064,6 @@ CHECK_DEPS = libgo.la libgobegin.a \
$(toolexeclibgocompress_DATA) \
$(toolexeclibgocontainer_DATA) \
$(toolexeclibgocrypto_DATA) \
- $(toolexeclibgocryptoopenpgp_DATA) \
$(toolexeclibgodebug_DATA) \
$(toolexeclibgoencoding_DATA) \
$(toolexeclibgoexp_DATA) \
@@ -2260,7 +2112,6 @@ TEST_PACKAGES = \
mime/check \
net/check \
os/check \
- patch/check \
path/check \
reflect/check \
regexp/check \
@@ -2271,7 +2122,6 @@ TEST_PACKAGES = \
sync/check \
time/check \
unicode/check \
- websocket/check \
archive/tar/check \
archive/zip/check \
compress/bzip2/check \
@@ -2283,35 +2133,22 @@ TEST_PACKAGES = \
container/list/check \
container/ring/check \
crypto/aes/check \
- crypto/bcrypt/check \
- crypto/blowfish/check \
- crypto/cast5/check \
crypto/cipher/check \
crypto/des/check \
crypto/dsa/check \
crypto/ecdsa/check \
crypto/elliptic/check \
crypto/hmac/check \
- crypto/md4/check \
crypto/md5/check \
- crypto/ocsp/check \
- crypto/openpgp/check \
crypto/rand/check \
crypto/rc4/check \
- crypto/ripemd160/check \
crypto/rsa/check \
crypto/sha1/check \
crypto/sha256/check \
crypto/sha512/check \
crypto/subtle/check \
crypto/tls/check \
- crypto/twofish/check \
crypto/x509/check \
- crypto/xtea/check \
- crypto/openpgp/armor/check \
- crypto/openpgp/elgamal/check \
- crypto/openpgp/packet/check \
- crypto/openpgp/s2k/check \
database/sql/check \
database/sql/driver/check \
debug/dwarf/check \
@@ -2324,18 +2161,16 @@ TEST_PACKAGES = \
encoding/base64/check \
encoding/binary/check \
encoding/csv/check \
- encoding/git85/check \
encoding/gob/check \
encoding/hex/check \
encoding/json/check \
encoding/pem/check \
encoding/xml/check \
exp/ebnf/check \
+ exp/html/check \
$(exp_inotify_check) \
exp/norm/check \
exp/proxy/check \
- exp/spdy/check \
- exp/ssh/check \
exp/terminal/check \
exp/utf8string/check \
html/template/check \
@@ -3353,26 +3188,6 @@ uninstall-toolexeclibgocryptoDATA:
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgocryptodir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgocryptodir)" && rm -f $$files
-install-toolexeclibgocryptoopenpgpDATA: $(toolexeclibgocryptoopenpgp_DATA)
- @$(NORMAL_INSTALL)
- test -z "$(toolexeclibgocryptoopenpgpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)"
- @list='$(toolexeclibgocryptoopenpgp_DATA)'; test -n "$(toolexeclibgocryptoopenpgpdir)" || list=; \
- for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; \
- done | $(am__base_list) | \
- while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" || exit $$?; \
- done
-
-uninstall-toolexeclibgocryptoopenpgpDATA:
- @$(NORMAL_UNINSTALL)
- @list='$(toolexeclibgocryptoopenpgp_DATA)'; test -n "$(toolexeclibgocryptoopenpgpdir)" || list=; \
- files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$files" || exit 0; \
- echo " ( cd '$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" && rm -f $$files
install-toolexeclibgocryptox509DATA: $(toolexeclibgocryptox509_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgocryptox509dir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptox509dir)"
@@ -4250,7 +4065,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@@ -4316,7 +4131,6 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgocompressDATA \
install-toolexeclibgocontainerDATA \
install-toolexeclibgocryptoDATA \
- install-toolexeclibgocryptoopenpgpDATA \
install-toolexeclibgocryptox509DATA \
install-toolexeclibgodatabaseDATA \
install-toolexeclibgodatabasesqlDATA \
@@ -4382,7 +4196,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgocompressDATA \
uninstall-toolexeclibgocontainerDATA \
uninstall-toolexeclibgocryptoDATA \
- uninstall-toolexeclibgocryptoopenpgpDATA \
uninstall-toolexeclibgocryptox509DATA \
uninstall-toolexeclibgodatabaseDATA \
uninstall-toolexeclibgodatabasesqlDATA \
@@ -4431,7 +4244,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgocompressDATA \
install-toolexeclibgocontainerDATA \
install-toolexeclibgocryptoDATA \
- install-toolexeclibgocryptoopenpgpDATA \
install-toolexeclibgocryptox509DATA \
install-toolexeclibgodatabaseDATA \
install-toolexeclibgodatabasesqlDATA \
@@ -4461,7 +4273,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgocompressDATA \
uninstall-toolexeclibgocontainerDATA \
uninstall-toolexeclibgocryptoDATA \
- uninstall-toolexeclibgocryptoopenpgpDATA \
uninstall-toolexeclibgocryptox509DATA \
uninstall-toolexeclibgodatabaseDATA \
uninstall-toolexeclibgodatabasesqlDATA \
@@ -4737,15 +4548,6 @@ signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
$(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
mv -f $@.tmp $@
-@go_include@ patch/patch.lo.dep
-patch/patch.lo.dep: $(go_patch_files)
- $(BUILDDEPS)
-patch/patch.lo: $(go_patch_files)
- $(BUILDPACKAGE)
-patch/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: patch/check
-
@go_include@ path/path.lo.dep
path/path.lo.dep: $(go_path_files)
$(BUILDDEPS)
@@ -4855,15 +4657,6 @@ unicode/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: unicode/check
-@go_include@ websocket/websocket.lo.dep
-websocket/websocket.lo.dep: $(go_websocket_files)
- $(BUILDDEPS)
-websocket/websocket.lo: $(go_websocket_files)
- $(BUILDPACKAGE)
-websocket/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: websocket/check
-
@go_include@ archive/tar.lo.dep
archive/tar.lo.dep: $(go_archive_tar_files)
$(BUILDDEPS)
@@ -4974,36 +4767,6 @@ crypto/aes/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/aes/check
-@go_include@ crypto/bcrypt.lo.dep
-crypto/bcrypt.lo.dep: $(go_crypto_bcrypt_files)
- $(BUILDDEPS)
-crypto/bcrypt.lo: $(go_crypto_bcrypt_files)
- $(BUILDPACKAGE)
-crypto/bcrypt/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/bcrypt
- @$(CHECK)
-.PHONY: crypto/bcrypt/check
-
-@go_include@ crypto/blowfish.lo.dep
-crypto/blowfish.lo.dep: $(go_crypto_blowfish_files)
- $(BUILDDEPS)
-crypto/blowfish.lo: $(go_crypto_blowfish_files)
- $(BUILDPACKAGE)
-crypto/blowfish/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/blowfish
- @$(CHECK)
-.PHONY: crypto/blowfish/check
-
-@go_include@ crypto/cast5.lo.dep
-crypto/cast5.lo.dep: $(go_crypto_cast5_files)
- $(BUILDDEPS)
-crypto/cast5.lo: $(go_crypto_cast5_files)
- $(BUILDPACKAGE)
-crypto/cast5/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/cast5
- @$(CHECK)
-.PHONY: crypto/cast5/check
-
@go_include@ crypto/cipher.lo.dep
crypto/cipher.lo.dep: $(go_crypto_cipher_files)
$(BUILDDEPS)
@@ -5064,16 +4827,6 @@ crypto/hmac/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/hmac/check
-@go_include@ crypto/md4.lo.dep
-crypto/md4.lo.dep: $(go_crypto_md4_files)
- $(BUILDDEPS)
-crypto/md4.lo: $(go_crypto_md4_files)
- $(BUILDPACKAGE)
-crypto/md4/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/md4
- @$(CHECK)
-.PHONY: crypto/md4/check
-
@go_include@ crypto/md5.lo.dep
crypto/md5.lo.dep: $(go_crypto_md5_files)
$(BUILDDEPS)
@@ -5084,26 +4837,6 @@ crypto/md5/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/md5/check
-@go_include@ crypto/ocsp.lo.dep
-crypto/ocsp.lo.dep: $(go_crypto_ocsp_files)
- $(BUILDDEPS)
-crypto/ocsp.lo: $(go_crypto_ocsp_files)
- $(BUILDPACKAGE)
-crypto/ocsp/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/ocsp
- @$(CHECK)
-.PHONY: crypto/ocsp/check
-
-@go_include@ crypto/openpgp.lo.dep
-crypto/openpgp.lo.dep: $(go_crypto_openpgp_files)
- $(BUILDDEPS)
-crypto/openpgp.lo: $(go_crypto_openpgp_files)
- $(BUILDPACKAGE)
-crypto/openpgp/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp
- @$(CHECK)
-.PHONY: crypto/openpgp/check
-
@go_include@ crypto/rand.lo.dep
crypto/rand.lo.dep: $(go_crypto_rand_files)
$(BUILDDEPS)
@@ -5124,16 +4857,6 @@ crypto/rc4/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/rc4/check
-@go_include@ crypto/ripemd160.lo.dep
-crypto/ripemd160.lo.dep: $(go_crypto_ripemd160_files)
- $(BUILDDEPS)
-crypto/ripemd160.lo: $(go_crypto_ripemd160_files)
- $(BUILDPACKAGE)
-crypto/ripemd160/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/ripemd160
- @$(CHECK)
-.PHONY: crypto/ripemd160/check
-
@go_include@ crypto/rsa.lo.dep
crypto/rsa.lo.dep: $(go_crypto_rsa_files)
$(BUILDDEPS)
@@ -5194,16 +4917,6 @@ crypto/tls/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/tls/check
-@go_include@ crypto/twofish.lo.dep
-crypto/twofish.lo.dep: $(go_crypto_twofish_files)
- $(BUILDDEPS)
-crypto/twofish.lo: $(go_crypto_twofish_files)
- $(BUILDPACKAGE)
-crypto/twofish/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/twofish
- @$(CHECK)
-.PHONY: crypto/twofish/check
-
@go_include@ crypto/x509.lo.dep
crypto/x509.lo.dep: $(go_crypto_x509_files)
$(BUILDDEPS)
@@ -5214,66 +4927,6 @@ crypto/x509/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/x509/check
-@go_include@ crypto/xtea.lo.dep
-crypto/xtea.lo.dep: $(go_crypto_xtea_files)
- $(BUILDDEPS)
-crypto/xtea.lo: $(go_crypto_xtea_files)
- $(BUILDPACKAGE)
-crypto/xtea/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/xtea
- @$(CHECK)
-.PHONY: crypto/xtea/check
-
-@go_include@ crypto/openpgp/armor.lo.dep
-crypto/openpgp/armor.lo.dep: $(go_crypto_openpgp_armor_files)
- $(BUILDDEPS)
-crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files)
- $(BUILDPACKAGE)
-crypto/openpgp/armor/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/armor
- @$(CHECK)
-.PHONY: crypto/openpgp/armor/check
-
-@go_include@ crypto/openpgp/elgamal.lo.dep
-crypto/openpgp/elgamal.lo.dep: $(go_crypto_openpgp_elgamal_files)
- $(BUILDDEPS)
-crypto/openpgp/elgamal.lo: $(go_crypto_openpgp_elgamal_files)
- $(BUILDPACKAGE)
-crypto/openpgp/elgamal/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/elgamal
- @$(CHECK)
-.PHONY: crypto/openpgp/elgamal/check
-
-@go_include@ crypto/openpgp/errors.lo.dep
-crypto/openpgp/errors.lo.dep: $(go_crypto_openpgp_errors_files)
- $(BUILDDEPS)
-crypto/openpgp/errors.lo: $(go_crypto_openpgp_errors_files)
- $(BUILDPACKAGE)
-crypto/openpgp/errors/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/errors
- @$(CHECK)
-.PHONY: crypto/openpgp/errors/check
-
-@go_include@ crypto/openpgp/packet.lo.dep
-crypto/openpgp/packet.lo.dep: $(go_crypto_openpgp_packet_files)
- $(BUILDDEPS)
-crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files)
- $(BUILDPACKAGE)
-crypto/openpgp/packet/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/packet
- @$(CHECK)
-.PHONY: crypto/openpgp/packet/check
-
-@go_include@ crypto/openpgp/s2k.lo.dep
-crypto/openpgp/s2k.lo.dep: $(go_crypto_openpgp_s2k_files)
- $(BUILDDEPS)
-crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files)
- $(BUILDPACKAGE)
-crypto/openpgp/s2k/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/openpgp/s2k
- @$(CHECK)
-.PHONY: crypto/openpgp/s2k/check
-
@go_include@ crypto/x509/pkix.lo.dep
crypto/x509/pkix.lo.dep: $(go_crypto_x509_pkix_files)
$(BUILDDEPS)
@@ -5414,16 +5067,6 @@ encoding/csv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: encoding/csv/check
-@go_include@ encoding/git85.lo.dep
-encoding/git85.lo.dep: $(go_encoding_git85_files)
- $(BUILDDEPS)
-encoding/git85.lo: $(go_encoding_git85_files)
- $(BUILDPACKAGE)
-encoding/git85/check: $(CHECK_DEPS)
- @$(MKDIR_P) encoding/git85
- @$(CHECK)
-.PHONY: encoding/git85/check
-
@go_include@ encoding/gob.lo.dep
encoding/gob.lo.dep: $(go_encoding_gob_files)
$(BUILDDEPS)
@@ -5484,6 +5127,16 @@ exp/ebnf/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/ebnf/check
+@go_include@ exp/html.lo.dep
+exp/html.lo.dep: $(go_exp_html_files)
+ $(BUILDDEPS)
+exp/html.lo: $(go_exp_html_files)
+ $(BUILDPACKAGE)
+exp/html/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/html
+ @$(CHECK)
+.PHONY: exp/html/check
+
@go_include@ exp/norm.lo.dep
exp/norm.lo.dep: $(go_exp_norm_files)
$(BUILDDEPS)
@@ -5504,26 +5157,6 @@ exp/proxy/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/proxy/check
-@go_include@ exp/spdy.lo.dep
-exp/spdy.lo.dep: $(go_exp_spdy_files)
- $(BUILDDEPS)
-exp/spdy.lo: $(go_exp_spdy_files)
- $(BUILDPACKAGE)
-exp/spdy/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/spdy
- @$(CHECK)
-.PHONY: exp/spdy/check
-
-@go_include@ exp/ssh.lo.dep
-exp/ssh.lo.dep: $(go_exp_ssh_files)
- $(BUILDDEPS)
-exp/ssh.lo: $(go_exp_ssh_files)
- $(BUILDPACKAGE)
-exp/ssh/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/ssh
- @$(CHECK)
-.PHONY: exp/ssh/check
-
@go_include@ exp/terminal.lo.dep
exp/terminal.lo.dep: $(go_exp_terminal_files)
$(BUILDDEPS)
@@ -5835,12 +5468,6 @@ mime/multipart/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: mime/multipart/check
-@go_include@ net/dict.lo.dep
-net/dict.lo.dep: $(go_net_dict_files)
- $(BUILDDEPS)
-net/dict.lo: $(go_net_dict_files)
- $(BUILDPACKAGE)
-
@go_include@ net/http.lo.dep
net/http.lo.dep: $(go_net_http_files)
$(BUILDDEPS)
@@ -6194,8 +5821,6 @@ net.gox: net/net.lo
$(BUILDGOX)
os.gox: os/os.lo
$(BUILDGOX)
-patch.gox: patch/patch.lo
- $(BUILDGOX)
path.gox: path/path.lo
$(BUILDGOX)
reflect.gox: reflect/reflect.lo
@@ -6220,8 +5845,6 @@ time.gox: time/time.lo
$(BUILDGOX)
unicode.gox: unicode/unicode.lo
$(BUILDGOX)
-websocket.gox: websocket/websocket.lo
- $(BUILDGOX)
archive/tar.gox: archive/tar.lo
$(BUILDGOX)
@@ -6248,12 +5871,6 @@ container/ring.gox: container/ring.lo
crypto/aes.gox: crypto/aes.lo
$(BUILDGOX)
-crypto/bcrypt.gox: crypto/bcrypt.lo
- $(BUILDGOX)
-crypto/blowfish.gox: crypto/blowfish.lo
- $(BUILDGOX)
-crypto/cast5.gox: crypto/cast5.lo
- $(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX)
crypto/des.gox: crypto/des.lo
@@ -6266,20 +5883,12 @@ crypto/elliptic.gox: crypto/elliptic.lo
$(BUILDGOX)
crypto/hmac.gox: crypto/hmac.lo
$(BUILDGOX)
-crypto/md4.gox: crypto/md4.lo
- $(BUILDGOX)
crypto/md5.gox: crypto/md5.lo
$(BUILDGOX)
-crypto/ocsp.gox: crypto/ocsp.lo
- $(BUILDGOX)
-crypto/openpgp.gox: crypto/openpgp.lo
- $(BUILDGOX)
crypto/rand.gox: crypto/rand.lo
$(BUILDGOX)
crypto/rc4.gox: crypto/rc4.lo
$(BUILDGOX)
-crypto/ripemd160.gox: crypto/ripemd160.lo
- $(BUILDGOX)
crypto/rsa.gox: crypto/rsa.lo
$(BUILDGOX)
crypto/sha1.gox: crypto/sha1.lo
@@ -6292,23 +5901,8 @@ crypto/subtle.gox: crypto/subtle.lo
$(BUILDGOX)
crypto/tls.gox: crypto/tls.lo
$(BUILDGOX)
-crypto/twofish.gox: crypto/twofish.lo
- $(BUILDGOX)
crypto/x509.gox: crypto/x509.lo
$(BUILDGOX)
-crypto/xtea.gox: crypto/xtea.lo
- $(BUILDGOX)
-
-crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
- $(BUILDGOX)
-crypto/openpgp/elgamal.gox: crypto/openpgp/elgamal.lo
- $(BUILDGOX)
-crypto/openpgp/errors.gox: crypto/openpgp/errors.lo
- $(BUILDGOX)
-crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
- $(BUILDGOX)
-crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
- $(BUILDGOX)
crypto/x509/pkix.gox: crypto/x509/pkix.lo
$(BUILDGOX)
@@ -6342,8 +5936,6 @@ encoding/binary.gox: encoding/binary.lo
$(BUILDGOX)
encoding/csv.gox: encoding/csv.lo
$(BUILDGOX)
-encoding/git85.gox: encoding/git85.lo
- $(BUILDGOX)
encoding/gob.gox: encoding/gob.lo
$(BUILDGOX)
encoding/hex.gox: encoding/hex.lo
@@ -6357,16 +5949,14 @@ encoding/xml.gox: encoding/xml.lo
exp/ebnf.gox: exp/ebnf.lo
$(BUILDGOX)
+exp/html.gox: exp/html.lo
+ $(BUILDGOX)
exp/inotify.gox: exp/inotify.lo
$(BUILDGOX)
exp/norm.gox: exp/norm.lo
$(BUILDGOX)
exp/proxy.gox: exp/proxy.lo
$(BUILDGOX)
-exp/spdy.gox: exp/spdy.lo
- $(BUILDGOX)
-exp/ssh.gox: exp/ssh.lo
- $(BUILDGOX)
exp/terminal.gox: exp/terminal.lo
$(BUILDGOX)
exp/types.gox: exp/types.lo
@@ -6435,8 +6025,6 @@ math/rand.gox: math/rand.lo
mime/multipart.gox: mime/multipart.lo
$(BUILDGOX)
-net/dict.gox: net/dict.lo
- $(BUILDGOX)
net/http.gox: net/http.lo
$(BUILDGOX)
net/mail.gox: net/mail.lo
diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go
index 13fe2700f9b..755a730c8b4 100644
--- a/libgo/go/archive/tar/reader.go
+++ b/libgo/go/archive/tar/reader.go
@@ -18,7 +18,7 @@ import (
)
var (
- HeaderError = errors.New("invalid tar header")
+ ErrHeader = errors.New("invalid tar header")
)
// A Reader provides sequential access to the contents of a tar archive.
@@ -123,13 +123,13 @@ func (tr *Reader) readHeader() *Header {
if bytes.Equal(header, zeroBlock[0:blockSize]) {
tr.err = io.EOF
} else {
- tr.err = HeaderError // zero block and then non-zero block
+ tr.err = ErrHeader // zero block and then non-zero block
}
return nil
}
if !tr.verifyChecksum(header) {
- tr.err = HeaderError
+ tr.err = ErrHeader
return nil
}
@@ -188,7 +188,7 @@ func (tr *Reader) readHeader() *Header {
}
if tr.err != nil {
- tr.err = HeaderError
+ tr.err = ErrHeader
return nil
}
diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go
index 0a6513d0cac..0a8646c393f 100644
--- a/libgo/go/archive/tar/reader_test.go
+++ b/libgo/go/archive/tar/reader_test.go
@@ -240,31 +240,20 @@ func TestNonSeekable(t *testing.T) {
}
defer f.Close()
- // pipe the data in
- r, w, err := os.Pipe()
- if err != nil {
- t.Fatalf("Unexpected error %s", err)
+ type readerOnly struct {
+ io.Reader
}
- go func() {
- rdbuf := make([]uint8, 1<<16)
- for {
- nr, err := f.Read(rdbuf)
- w.Write(rdbuf[0:nr])
- if err == io.EOF {
- break
- }
- }
- w.Close()
- }()
-
- tr := NewReader(r)
+ tr := NewReader(readerOnly{f})
nread := 0
for ; ; nread++ {
- hdr, err := tr.Next()
- if hdr == nil || err == io.EOF {
+ _, err := tr.Next()
+ if err == io.EOF {
break
}
+ if err != nil {
+ t.Fatalf("Unexpected error: %v", err)
+ }
}
if nread != len(test.headers) {
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index 4365009a308..4dd0f4f4344 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -17,9 +17,9 @@ import (
)
var (
- FormatError = errors.New("zip: not a valid zip file")
- UnsupportedMethod = errors.New("zip: unsupported compression algorithm")
- ChecksumError = errors.New("zip: checksum error")
+ ErrFormat = errors.New("zip: not a valid zip file")
+ ErrAlgorithm = errors.New("zip: unsupported compression algorithm")
+ ErrChecksum = errors.New("zip: checksum error")
)
type Reader struct {
@@ -90,12 +90,12 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
// The count of files inside a zip is truncated to fit in a uint16.
// Gloss over this by reading headers until we encounter
- // a bad one, and then only report a FormatError or UnexpectedEOF if
+ // a bad one, and then only report a ErrFormat or UnexpectedEOF if
// the file count modulo 65536 is incorrect.
for {
f := &File{zipr: r, zipsize: size}
err = readDirectoryHeader(f, buf)
- if err == FormatError || err == io.ErrUnexpectedEOF {
+ if err == ErrFormat || err == io.ErrUnexpectedEOF {
break
}
if err != nil {
@@ -135,7 +135,7 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
case Deflate:
rc = flate.NewReader(r)
default:
- err = UnsupportedMethod
+ err = ErrAlgorithm
}
if rc != nil {
rc = &checksumReader{rc, crc32.NewIEEE(), f, r}
@@ -162,7 +162,7 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
}
}
if r.hash.Sum32() != r.f.CRC32 {
- err = ChecksumError
+ err = ErrChecksum
}
return
}
@@ -176,7 +176,7 @@ func readFileHeader(f *File, r io.Reader) error {
}
c := binary.LittleEndian
if sig := c.Uint32(b[:4]); sig != fileHeaderSignature {
- return FormatError
+ return ErrFormat
}
f.ReaderVersion = c.Uint16(b[4:6])
f.Flags = c.Uint16(b[6:8])
@@ -207,7 +207,7 @@ func (f *File) findBodyOffset() (int64, error) {
}
c := binary.LittleEndian
if sig := c.Uint32(b[:4]); sig != fileHeaderSignature {
- return 0, FormatError
+ return 0, ErrFormat
}
filenameLen := int(c.Uint16(b[26:28]))
extraLen := int(c.Uint16(b[28:30]))
@@ -216,7 +216,7 @@ func (f *File) findBodyOffset() (int64, error) {
// readDirectoryHeader attempts to read a directory header from r.
// It returns io.ErrUnexpectedEOF if it cannot read a complete header,
-// and FormatError if it doesn't find a valid header signature.
+// and ErrFormat if it doesn't find a valid header signature.
func readDirectoryHeader(f *File, r io.Reader) error {
var b [directoryHeaderLen]byte
if _, err := io.ReadFull(r, b[:]); err != nil {
@@ -224,7 +224,7 @@ func readDirectoryHeader(f *File, r io.Reader) error {
}
c := binary.LittleEndian
if sig := c.Uint32(b[:4]); sig != directoryHeaderSignature {
- return FormatError
+ return ErrFormat
}
f.CreatorVersion = c.Uint16(b[4:6])
f.ReaderVersion = c.Uint16(b[6:8])
@@ -280,7 +280,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
break
}
if i == 1 || bLen == size {
- return nil, FormatError
+ return nil, ErrFormat
}
}
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index 0e40268c2f8..9407e35d5c0 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -70,7 +70,7 @@ var tests = []ZipTest{
},
},
{Name: "readme.zip"},
- {Name: "readme.notzip", Error: FormatError},
+ {Name: "readme.notzip", Error: ErrFormat},
{
Name: "dd.zip",
File: []ZipTestFile{
@@ -131,7 +131,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
}
// bail if file is not zip
- if err == FormatError {
+ if err == ErrFormat {
return
}
defer func() {
@@ -184,8 +184,8 @@ func readTestZip(t *testing.T, zt ZipTest) {
}
var b bytes.Buffer
_, err = io.Copy(&b, r)
- if err != ChecksumError {
- t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
+ if err != ErrChecksum {
+ t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ErrChecksum)
}
}
}
@@ -250,13 +250,9 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
}
func testFileMode(t *testing.T, f *File, want os.FileMode) {
- mode, err := f.Mode()
+ mode := f.Mode()
if want == 0 {
- if err == nil {
- t.Errorf("%s mode: got %v, want none", f.Name, mode)
- }
- } else if err != nil {
- t.Errorf("%s mode: %s", f.Name, err)
+ t.Errorf("%s mode: got %v, want none", f.Name, mode)
} else if mode != want {
t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
}
@@ -268,8 +264,8 @@ func TestInvalidFiles(t *testing.T) {
// zeroes
_, err := NewReader(sliceReaderAt(b), size)
- if err != FormatError {
- t.Errorf("zeroes: error=%v, want %v", err, FormatError)
+ if err != ErrFormat {
+ t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
}
// repeated directoryEndSignatures
@@ -279,8 +275,8 @@ func TestInvalidFiles(t *testing.T) {
copy(b[i:i+4], sig)
}
_, err = NewReader(sliceReaderAt(b), size)
- if err != FormatError {
- t.Errorf("sigs: error=%v, want %v", err, FormatError)
+ if err != ErrFormat {
+ t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
}
}
diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go
index 34a87fae5b3..67e96586294 100644
--- a/libgo/go/archive/zip/struct.go
+++ b/libgo/go/archive/zip/struct.go
@@ -12,6 +12,7 @@ This package does not support ZIP64 or disk spanning.
package zip
import (
+ "errors"
"os"
"time"
)
@@ -55,6 +56,38 @@ type FileHeader struct {
Comment string
}
+// FileInfo returns an os.FileInfo for the FileHeader.
+func (fh *FileHeader) FileInfo() os.FileInfo {
+ return headerFileInfo{fh}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+ fh *FileHeader
+}
+
+func (fi headerFileInfo) Name() string { return fi.fh.Name }
+func (fi headerFileInfo) Size() int64 { return int64(fi.fh.UncompressedSize) }
+func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
+func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() }
+
+// FileInfoHeader creates a partially-populated FileHeader from an
+// os.FileInfo.
+func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
+ size := fi.Size()
+ if size > (1<<32 - 1) {
+ return nil, errors.New("zip: file over 4GB")
+ }
+ fh := &FileHeader{
+ Name: fi.Name(),
+ UncompressedSize: uint32(size),
+ }
+ fh.SetModTime(fi.ModTime())
+ fh.SetMode(fi.Mode())
+ return fh, nil
+}
+
type directoryEnd struct {
diskNbr uint16 // unused
dirDiskNbr uint16 // unused
@@ -131,8 +164,7 @@ const (
)
// Mode returns the permission and mode bits for the FileHeader.
-// An error is returned in case the information is not available.
-func (h *FileHeader) Mode() (mode os.FileMode, err error) {
+func (h *FileHeader) Mode() (mode os.FileMode) {
switch h.CreatorVersion >> 8 {
case creatorUnix, creatorMacOSX:
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
@@ -142,7 +174,7 @@ func (h *FileHeader) Mode() (mode os.FileMode, err error) {
if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
mode |= os.ModeDir
}
- return mode, nil
+ return mode
}
// SetMode changes the permission and mode bits for the FileHeader.
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index a1530644eee..b1b128e2a7d 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -129,7 +129,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
case Deflate:
fw.comp = flate.NewWriter(fw.compCount, 5)
default:
- return nil, UnsupportedMethod
+ return nil, ErrAlgorithm
}
fw.rawCount = &countWriter{w: fw.comp}
diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go
index 8aab2b68123..acd3d938218 100644
--- a/libgo/go/archive/zip/zip_test.go
+++ b/libgo/go/archive/zip/zip_test.go
@@ -10,6 +10,7 @@ import (
"bytes"
"fmt"
"io"
+ "reflect"
"testing"
"time"
)
@@ -66,3 +67,22 @@ func TestModTime(t *testing.T) {
t.Errorf("times don't match: got %s, want %s", outTime, testTime)
}
}
+
+func TestFileHeaderRoundTrip(t *testing.T) {
+ fh := &FileHeader{
+ Name: "foo.txt",
+ UncompressedSize: 987654321,
+ ModifiedTime: 1234,
+ ModifiedDate: 5678,
+ }
+ fi := fh.FileInfo()
+ fh2, err := FileInfoHeader(fi)
+
+ // Ignore these fields:
+ fh2.CreatorVersion = 0
+ fh2.ExternalAttrs = 0
+
+ if !reflect.DeepEqual(fh, fh2) {
+ t.Errorf("mismatch\n input=%#v\noutput=%#v\nerr=%v", fh, fh2, err)
+ }
+}
diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go
index 77757af1d80..2c3eb6a596b 100644
--- a/libgo/go/bytes/buffer.go
+++ b/libgo/go/bytes/buffer.go
@@ -33,6 +33,9 @@ const (
opRead // Any other read operation.
)
+// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
+var ErrTooLarge = errors.New("bytes.Buffer: too large")
+
// Bytes returns a slice of the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len(). If the caller changes the contents of the
// returned slice, the contents of the buffer will change provided there
@@ -68,8 +71,9 @@ func (b *Buffer) Truncate(n int) {
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() { b.Truncate(0) }
-// Grow buffer to guarantee space for n more bytes.
-// Return index where bytes should be written.
+// grow grows the buffer to guarantee space for n more bytes.
+// It returns the index where bytes should be written.
+// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) grow(n int) int {
m := b.Len()
// If buffer is empty, reset to recover space.
@@ -82,7 +86,7 @@ func (b *Buffer) grow(n int) int {
buf = b.bootstrap[0:]
} else {
// not enough space anywhere
- buf = make([]byte, 2*cap(b.buf)+n)
+ buf = makeSlice(2*cap(b.buf) + n)
copy(buf, b.buf[b.off:])
}
b.buf = buf
@@ -94,6 +98,8 @@ func (b *Buffer) grow(n int) int {
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
+// If the buffer becomes too large, Write will panic with
+// ErrTooLarge.
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
@@ -102,6 +108,8 @@ func (b *Buffer) Write(p []byte) (n int, err error) {
// WriteString appends the contents of s to the buffer. The return
// value n is the length of s; err is always nil.
+// If the buffer becomes too large, WriteString will panic with
+// ErrTooLarge.
func (b *Buffer) WriteString(s string) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(s))
@@ -118,6 +126,8 @@ const MinRead = 512
// The return value n is the number of bytes read.
// Any error except io.EOF encountered during the read
// is also returned.
+// If the buffer becomes too large, ReadFrom will panic with
+// ErrTooLarge.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
b.lastRead = opInvalid
// If buffer is empty, reset to recover space.
@@ -125,18 +135,16 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
b.Truncate(0)
}
for {
- if cap(b.buf)-len(b.buf) < MinRead {
- var newBuf []byte
- // can we get space without allocation?
- if b.off+cap(b.buf)-len(b.buf) >= MinRead {
- // reuse beginning of buffer
- newBuf = b.buf[0 : len(b.buf)-b.off]
- } else {
- // not enough space at end; put space on end
- newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
+ if free := cap(b.buf) - len(b.buf); free < MinRead {
+ // not enough space at end
+ newBuf := b.buf
+ if b.off+free < MinRead {
+ // not enough space using beginning of buffer;
+ // double buffer capacity
+ newBuf = makeSlice(2*cap(b.buf) + MinRead)
}
copy(newBuf, b.buf[b.off:])
- b.buf = newBuf
+ b.buf = newBuf[:len(b.buf)-b.off]
b.off = 0
}
m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
@@ -152,6 +160,18 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
return n, nil // err is EOF, so return nil explicitly
}
+// makeSlice allocates a slice of size n. If the allocation fails, it panics
+// with ErrTooLarge.
+func makeSlice(n int) []byte {
+ // If the make fails, give a known error.
+ defer func() {
+ if recover() != nil {
+ panic(ErrTooLarge)
+ }
+ }()
+ return make([]byte, n)
+}
+
// WriteTo writes data to w until the buffer is drained or an error
// occurs. The return value n is the number of bytes written; it always
// fits into an int, but it is int64 to match the io.WriterTo interface.
@@ -176,6 +196,8 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
+// If the buffer becomes too large, WriteByte will panic with
+// ErrTooLarge.
func (b *Buffer) WriteByte(c byte) error {
b.lastRead = opInvalid
m := b.grow(1)
@@ -187,6 +209,8 @@ func (b *Buffer) WriteByte(c byte) error {
// code point r to the buffer, returning its length and
// an error, which is always nil but is included
// to match bufio.Writer's WriteRune.
+// If the buffer becomes too large, WriteRune will panic with
+// ErrTooLarge.
func (b *Buffer) WriteRune(r rune) (n int, err error) {
if r < utf8.RuneSelf {
b.WriteByte(byte(r))
diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go
index 4f744457dd7..1e725890b73 100644
--- a/libgo/go/compress/flate/deflate.go
+++ b/libgo/go/compress/flate/deflate.go
@@ -27,10 +27,12 @@ const (
// stop things from getting too large.
maxFlateBlockTokens = 1 << 14
maxStoreBlockSize = 65535
- hashBits = 15
+ hashBits = 17
hashSize = 1 << hashBits
hashMask = (1 << hashBits) - 1
hashShift = (hashBits + minMatchLength - 1) / minMatchLength
+
+ skipNever = math.MaxInt32
)
type compressionLevel struct {
@@ -45,12 +47,12 @@ var levels = []compressionLevel{
{3, 0, 32, 32, 6},
// Levels 4-9 use increasingly more lazy matching
// and increasingly stringent conditions for "good enough".
- {4, 4, 16, 16, math.MaxInt32},
- {8, 16, 32, 32, math.MaxInt32},
- {8, 16, 128, 128, math.MaxInt32},
- {8, 32, 128, 256, math.MaxInt32},
- {32, 128, 258, 1024, math.MaxInt32},
- {32, 258, 258, 4096, math.MaxInt32},
+ {4, 4, 16, 16, skipNever},
+ {8, 16, 32, 32, skipNever},
+ {8, 16, 128, 128, skipNever},
+ {8, 32, 128, 256, skipNever},
+ {32, 128, 258, 1024, skipNever},
+ {32, 258, 258, 4096, skipNever},
}
type compressor struct {
@@ -68,9 +70,10 @@ type compressor struct {
// If hashHead[hashValue] is within the current window, then
// hashPrev[hashHead[hashValue] & windowMask] contains the previous index
// with the same hash value.
- chainHead int
- hashHead []int
- hashPrev []int
+ chainHead int
+ hashHead []int
+ hashPrev []int
+ hashOffset int
// input window: unprocessed data is window[index:windowEnd]
index int
@@ -79,9 +82,8 @@ type compressor struct {
blockStart int // window index where current tokens start
byteAvailable bool // if true, still need to process window[index-1].
- // queued output tokens: tokens[:ti]
+ // queued output tokens
tokens []token
- ti int
// deflate state
length int
@@ -100,22 +102,9 @@ func (d *compressor) fillDeflate(b []byte) int {
if d.blockStart >= windowSize {
d.blockStart -= windowSize
} else {
- d.blockStart = math.MaxInt32
- }
- for i, h := range d.hashHead {
- v := h - windowSize
- if v < -1 {
- v = -1
- }
- d.hashHead[i] = v
- }
- for i, h := range d.hashPrev {
- v := -h - windowSize
- if v < -1 {
- v = -1
- }
- d.hashPrev[i] = v
+ d.blockStart = skipNever
}
+ d.hashOffset += windowSize
}
n := copy(d.window[d.windowEnd:], b)
d.windowEnd += n
@@ -186,7 +175,7 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
// hashPrev[i & windowMask] has already been overwritten, so stop now.
break
}
- if i = d.hashPrev[i&windowMask]; i < minIndex || i < 0 {
+ if i = d.hashPrev[i&windowMask] - d.hashOffset; i < minIndex || i < 0 {
break
}
}
@@ -205,13 +194,12 @@ func (d *compressor) initDeflate() {
d.hashHead = make([]int, hashSize)
d.hashPrev = make([]int, windowSize)
d.window = make([]byte, 2*windowSize)
- fillInts(d.hashHead, -1)
- d.tokens = make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1)
+ d.hashOffset = 1
+ d.tokens = make([]token, 0, maxFlateBlockTokens+1)
d.length = minMatchLength - 1
d.offset = 0
d.byteAvailable = false
d.index = 0
- d.ti = 0
d.hash = 0
d.chainHead = -1
}
@@ -243,15 +231,14 @@ Loop:
// Flush current output block if any.
if d.byteAvailable {
// There is still one pending token that needs to be flushed
- d.tokens[d.ti] = literalToken(uint32(d.window[d.index-1]))
- d.ti++
+ d.tokens = append(d.tokens, literalToken(uint32(d.window[d.index-1])))
d.byteAvailable = false
}
- if d.ti > 0 {
- if d.err = d.writeBlock(d.tokens[0:d.ti], d.index, false); d.err != nil {
+ if len(d.tokens) > 0 {
+ if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
return
}
- d.ti = 0
+ d.tokens = d.tokens[:0]
}
break Loop
}
@@ -261,7 +248,7 @@ Loop:
d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask
d.chainHead = d.hashHead[d.hash]
d.hashPrev[d.index&windowMask] = d.chainHead
- d.hashHead[d.hash] = d.index
+ d.hashHead[d.hash] = d.index + d.hashOffset
}
prevLength := d.length
prevOffset := d.offset
@@ -272,34 +259,33 @@ Loop:
minIndex = 0
}
- if d.chainHead >= minIndex &&
- (d.fastSkipHashing != 0 && lookahead > minMatchLength-1 ||
- d.fastSkipHashing == 0 && lookahead > prevLength && prevLength < d.lazy) {
- if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead, minMatchLength-1, lookahead); ok {
+ if d.chainHead-d.hashOffset >= minIndex &&
+ (d.fastSkipHashing != skipNever && lookahead > minMatchLength-1 ||
+ d.fastSkipHashing == skipNever && lookahead > prevLength && prevLength < d.lazy) {
+ if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
d.length = newLength
d.offset = newOffset
}
}
- if d.fastSkipHashing != 0 && d.length >= minMatchLength ||
- d.fastSkipHashing == 0 && prevLength >= minMatchLength && d.length <= prevLength {
+ if d.fastSkipHashing != skipNever && d.length >= minMatchLength ||
+ d.fastSkipHashing == skipNever && prevLength >= minMatchLength && d.length <= prevLength {
// There was a match at the previous step, and the current match is
// not better. Output the previous match.
- if d.fastSkipHashing != 0 {
- d.tokens[d.ti] = matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize))
+ if d.fastSkipHashing != skipNever {
+ d.tokens = append(d.tokens, matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize)))
} else {
- d.tokens[d.ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize))
+ d.tokens = append(d.tokens, matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize)))
}
- d.ti++
// Insert in the hash table all strings up to the end of the match.
// index and index-1 are already inserted. If there is not enough
// lookahead, the last two strings are not inserted into the hash
// table.
if d.length <= d.fastSkipHashing {
var newIndex int
- if d.fastSkipHashing != 0 {
+ if d.fastSkipHashing != skipNever {
newIndex = d.index + d.length
} else {
- newIndex = prevLength - 1
+ newIndex = d.index + prevLength - 1
}
for d.index++; d.index < newIndex; d.index++ {
if d.index < d.maxInsertIndex {
@@ -308,10 +294,10 @@ Loop:
// Our chain should point to the previous value.
d.hashPrev[d.index&windowMask] = d.hashHead[d.hash]
// Set the head of the hash chain to us.
- d.hashHead[d.hash] = d.index
+ d.hashHead[d.hash] = d.index + d.hashOffset
}
}
- if d.fastSkipHashing == 0 {
+ if d.fastSkipHashing == skipNever {
d.byteAvailable = false
d.length = minMatchLength - 1
}
@@ -323,30 +309,29 @@ Loop:
d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
}
}
- if d.ti == maxFlateBlockTokens {
+ if len(d.tokens) == maxFlateBlockTokens {
// The block includes the current character
if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
return
}
- d.ti = 0
+ d.tokens = d.tokens[:0]
}
} else {
- if d.fastSkipHashing != 0 || d.byteAvailable {
+ if d.fastSkipHashing != skipNever || d.byteAvailable {
i := d.index - 1
- if d.fastSkipHashing != 0 {
+ if d.fastSkipHashing != skipNever {
i = d.index
}
- d.tokens[d.ti] = literalToken(uint32(d.window[i]))
- d.ti++
- if d.ti == maxFlateBlockTokens {
+ d.tokens = append(d.tokens, literalToken(uint32(d.window[i])))
+ if len(d.tokens) == maxFlateBlockTokens {
if d.err = d.writeBlock(d.tokens, i+1, false); d.err != nil {
return
}
- d.ti = 0
+ d.tokens = d.tokens[:0]
}
}
d.index++
- if d.fastSkipHashing == 0 {
+ if d.fastSkipHashing == skipNever {
d.byteAvailable = true
}
}
diff --git a/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go
index bae5c82305a..24881d31c06 100644
--- a/libgo/go/compress/flate/deflate_test.go
+++ b/libgo/go/compress/flate/deflate_test.go
@@ -225,10 +225,17 @@ func testSync(t *testing.T, level int, input []byte, name string) {
}
func testToFromWithLevel(t *testing.T, level int, input []byte, name string) error {
+ return testToFromWithLevelAndLimit(t, level, input, name, -1)
+}
+
+func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) error {
buffer := bytes.NewBuffer(nil)
w := NewWriter(buffer, level)
w.Write(input)
w.Close()
+ if limit > 0 && buffer.Len() > limit {
+ t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
+ }
r := NewReader(buffer)
out, err := ioutil.ReadAll(r)
if err != nil {
@@ -244,12 +251,16 @@ func testToFromWithLevel(t *testing.T, level int, input []byte, name string) err
return nil
}
-func testToFrom(t *testing.T, input []byte, name string) {
+func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) {
for i := 0; i < 10; i++ {
- testToFromWithLevel(t, i, input, name)
+ testToFromWithLevelAndLimit(t, i, input, name, limit[i])
}
}
+func testToFrom(t *testing.T, input []byte, name string) {
+ testToFromWithLimit(t, input, name, [10]int{})
+}
+
func TestDeflateInflate(t *testing.T) {
for i, h := range deflateInflateTests {
testToFrom(t, h.in, fmt.Sprintf("#%d", i))
@@ -265,12 +276,33 @@ func TestReverseBits(t *testing.T) {
}
}
+type deflateInflateStringTest struct {
+ filename string
+ label string
+ limit [10]int
+}
+
+var deflateInflateStringTests = []deflateInflateStringTest{
+ {
+ "../testdata/e.txt",
+ "2.718281828...",
+ [...]int{10013, 5065, 5096, 5115, 5093, 5079, 5079, 5079, 5079, 5079},
+ },
+ {
+ "../testdata/Mark.Twain-Tom.Sawyer.txt",
+ "Mark.Twain-Tom.Sawyer",
+ [...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295},
+ },
+}
+
func TestDeflateInflateString(t *testing.T) {
- gold, err := ioutil.ReadFile("../testdata/e.txt")
- if err != nil {
- t.Error(err)
+ for _, test := range deflateInflateStringTests {
+ gold, err := ioutil.ReadFile(test.filename)
+ if err != nil {
+ t.Error(err)
+ }
+ testToFromWithLimit(t, gold, test.label, test.limit)
}
- testToFromWithLevel(t, 1, gold, "2.718281828...")
}
func TestReaderDict(t *testing.T) {
diff --git a/libgo/go/compress/flate/huffman_bit_writer.go b/libgo/go/compress/flate/huffman_bit_writer.go
index 8d0b4f9c1e8..57b56b5c96d 100644
--- a/libgo/go/compress/flate/huffman_bit_writer.go
+++ b/libgo/go/compress/flate/huffman_bit_writer.go
@@ -193,15 +193,17 @@ func (w *huffmanBitWriter) writeBytes(bytes []byte) {
// numLiterals The number of literals in literalEncoding
// numOffsets The number of offsets in offsetEncoding
func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
- fillInt32s(w.codegenFreq, 0)
+ for i := range w.codegenFreq {
+ w.codegenFreq[i] = 0
+ }
// Note that we are using codegen both as a temporary variable for holding
// a copy of the frequencies, and as the place where we put the result.
// This is fine because the output is always shorter than the input used
// so far.
codegen := w.codegen // cache
// Copy the concatenated code sizes to codegen. Put a marker at the end.
- copyUint8s(codegen[0:numLiterals], w.literalEncoding.codeBits)
- copyUint8s(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
+ copy(codegen[0:numLiterals], w.literalEncoding.codeBits)
+ copy(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
codegen[numLiterals+numOffsets] = badCode
size := codegen[0]
@@ -222,7 +224,10 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
w.codegenFreq[size]++
count--
for count >= 3 {
- n := min(count, 6)
+ n := 6
+ if n > count {
+ n = count
+ }
codegen[outIndex] = 16
outIndex++
codegen[outIndex] = uint8(n - 3)
@@ -232,7 +237,10 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
}
} else {
for count >= 11 {
- n := min(count, 138)
+ n := 138
+ if n > count {
+ n = count
+ }
codegen[outIndex] = 18
outIndex++
codegen[outIndex] = uint8(n - 11)
@@ -351,8 +359,12 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
if w.err != nil {
return
}
- fillInt32s(w.literalFreq, 0)
- fillInt32s(w.offsetFreq, 0)
+ for i := range w.literalFreq {
+ w.literalFreq[i] = 0
+ }
+ for i := range w.offsetFreq {
+ w.offsetFreq[i] = 0
+ }
n := len(tokens)
tokens = tokens[0 : n+1]
diff --git a/libgo/go/compress/flate/huffman_code.go b/libgo/go/compress/flate/huffman_code.go
index 7ed603a4f43..4873b0fce36 100644
--- a/libgo/go/compress/flate/huffman_code.go
+++ b/libgo/go/compress/flate/huffman_code.go
@@ -195,7 +195,9 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
// The tree can't have greater depth than n - 1, no matter what. This
// saves a little bit of work in some small cases
- maxBits = minInt32(maxBits, n-1)
+ if maxBits > n-1 {
+ maxBits = n - 1
+ }
// Create information about each of the levels.
// A bogus "Level 0" whose sole purpose is so that
diff --git a/libgo/go/compress/flate/util.go b/libgo/go/compress/flate/util.go
deleted file mode 100644
index aca5c78b2d4..00000000000
--- a/libgo/go/compress/flate/util.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package flate
-
-func min(left int, right int) int {
- if left < right {
- return left
- }
- return right
-}
-
-func minInt32(left int32, right int32) int32 {
- if left < right {
- return left
- }
- return right
-}
-
-func max(left int, right int) int {
- if left > right {
- return left
- }
- return right
-}
-
-func fillInts(a []int, value int) {
- for i := range a {
- a[i] = value
- }
-}
-
-func fillInt32s(a []int32, value int32) {
- for i := range a {
- a[i] = value
- }
-}
-
-func fillBytes(a []byte, value byte) {
- for i := range a {
- a[i] = value
- }
-}
-
-func fillInt8s(a []int8, value int8) {
- for i := range a {
- a[i] = value
- }
-}
-
-func fillUint8s(a []uint8, value uint8) {
- for i := range a {
- a[i] = value
- }
-}
-
-func copyInt8s(dst []int8, src []int8) int {
- cnt := min(len(dst), len(src))
- for i := 0; i < cnt; i++ {
- dst[i] = src[i]
- }
- return cnt
-}
-
-func copyUint8s(dst []uint8, src []uint8) int {
- cnt := min(len(dst), len(src))
- for i := 0; i < cnt; i++ {
- dst[i] = src[i]
- }
- return cnt
-}
diff --git a/libgo/go/compress/gzip/gunzip.go b/libgo/go/compress/gzip/gunzip.go
index 6d60fdd0ff3..d3743105d18 100644
--- a/libgo/go/compress/gzip/gunzip.go
+++ b/libgo/go/compress/gzip/gunzip.go
@@ -37,8 +37,8 @@ func makeReader(r io.Reader) flate.Reader {
return bufio.NewReader(r)
}
-var HeaderError = errors.New("invalid gzip header")
-var ChecksumError = errors.New("gzip checksum error")
+var ErrHeader = errors.New("invalid gzip header")
+var ErrChecksum = errors.New("gzip checksum error")
// The gzip file stores a header giving metadata about the compressed file.
// That header is exposed as the fields of the Compressor and Decompressor structs.
@@ -59,7 +59,7 @@ type Header struct {
// Only the first header is recorded in the Decompressor fields.
//
// Gzip files store a length and checksum of the uncompressed data.
-// The Decompressor will return a ChecksumError when Read
+// The Decompressor will return a ErrChecksum when Read
// reaches the end of the uncompressed data if it does not
// have the expected length or checksum. Clients should treat data
// returned by Read as tentative until they receive the successful
@@ -99,7 +99,7 @@ func (z *Decompressor) readString() (string, error) {
needconv := false
for i := 0; ; i++ {
if i >= len(z.buf) {
- return "", HeaderError
+ return "", ErrHeader
}
z.buf[i], err = z.r.ReadByte()
if err != nil {
@@ -137,7 +137,7 @@ func (z *Decompressor) readHeader(save bool) error {
return err
}
if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
- return HeaderError
+ return ErrHeader
}
z.flg = z.buf[3]
if save {
@@ -188,7 +188,7 @@ func (z *Decompressor) readHeader(save bool) error {
}
sum := z.digest.Sum32() & 0xFFFF
if n != sum {
- return HeaderError
+ return ErrHeader
}
}
@@ -221,7 +221,7 @@ func (z *Decompressor) Read(p []byte) (n int, err error) {
crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8])
sum := z.digest.Sum32()
if sum != crc32 || isize != z.size {
- z.err = ChecksumError
+ z.err = ErrChecksum
return 0, z.err
}
diff --git a/libgo/go/compress/gzip/gunzip_test.go b/libgo/go/compress/gzip/gunzip_test.go
index 771b0b6a1b4..a1333580dc0 100644
--- a/libgo/go/compress/gzip/gunzip_test.go
+++ b/libgo/go/compress/gzip/gunzip_test.go
@@ -232,7 +232,7 @@ var gunzipTests = []gunzipTest{
0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!', '!', '!',
},
- HeaderError,
+ ErrHeader,
},
{ // has 1 non-empty fixed huffman block not enough header
"hello.txt",
@@ -260,7 +260,7 @@ var gunzipTests = []gunzipTest{
0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x00,
0x00, 0x00,
},
- ChecksumError,
+ ErrChecksum,
},
{ // has 1 non-empty fixed huffman block but corrupt size
"hello.txt",
@@ -274,7 +274,7 @@ var gunzipTests = []gunzipTest{
0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0xff, 0x00,
0x00, 0x00,
},
- ChecksumError,
+ ErrChecksum,
},
}
diff --git a/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
new file mode 100644
index 00000000000..8d0ff4e65ce
--- /dev/null
+++ b/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
@@ -0,0 +1,8858 @@
+The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever. You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+
+Title: The Adventures of Tom Sawyer, Complete
+
+Author: Mark Twain (Samuel Clemens)
+
+Release Date: August 20, 2006 [EBook #74]
+[Last updated: May 3, 2011]
+
+Language: English
+
+
+*** START OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+
+
+
+Produced by David Widger. The previous edition was updated by Jose
+Menendez.
+
+
+
+
+
+ THE ADVENTURES OF TOM SAWYER
+ BY
+ MARK TWAIN
+ (Samuel Langhorne Clemens)
+
+
+
+
+ P R E F A C E
+
+MOST of the adventures recorded in this book really occurred; one or
+two were experiences of my own, the rest those of boys who were
+schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
+not from an individual--he is a combination of the characteristics of
+three boys whom I knew, and therefore belongs to the composite order of
+architecture.
+
+The odd superstitions touched upon were all prevalent among children
+and slaves in the West at the period of this story--that is to say,
+thirty or forty years ago.
+
+Although my book is intended mainly for the entertainment of boys and
+girls, I hope it will not be shunned by men and women on that account,
+for part of my plan has been to try to pleasantly remind adults of what
+they once were themselves, and of how they felt and thought and talked,
+and what queer enterprises they sometimes engaged in.
+
+ THE AUTHOR.
+
+HARTFORD, 1876.
+
+
+
+ T O M S A W Y E R
+
+
+
+CHAPTER I
+
+"TOM!"
+
+No answer.
+
+"TOM!"
+
+No answer.
+
+"What's gone with that boy, I wonder? You TOM!"
+
+No answer.
+
+The old lady pulled her spectacles down and looked over them about the
+room; then she put them up and looked out under them. She seldom or
+never looked THROUGH them for so small a thing as a boy; they were her
+state pair, the pride of her heart, and were built for "style," not
+service--she could have seen through a pair of stove-lids just as well.
+She looked perplexed for a moment, and then said, not fiercely, but
+still loud enough for the furniture to hear:
+
+"Well, I lay if I get hold of you I'll--"
+
+She did not finish, for by this time she was bending down and punching
+under the bed with the broom, and so she needed breath to punctuate the
+punches with. She resurrected nothing but the cat.
+
+"I never did see the beat of that boy!"
+
+She went to the open door and stood in it and looked out among the
+tomato vines and "jimpson" weeds that constituted the garden. No Tom.
+So she lifted up her voice at an angle calculated for distance and
+shouted:
+
+"Y-o-u-u TOM!"
+
+There was a slight noise behind her and she turned just in time to
+seize a small boy by the slack of his roundabout and arrest his flight.
+
+"There! I might 'a' thought of that closet. What you been doing in
+there?"
+
+"Nothing."
+
+"Nothing! Look at your hands. And look at your mouth. What IS that
+truck?"
+
+"I don't know, aunt."
+
+"Well, I know. It's jam--that's what it is. Forty times I've said if
+you didn't let that jam alone I'd skin you. Hand me that switch."
+
+The switch hovered in the air--the peril was desperate--
+
+"My! Look behind you, aunt!"
+
+The old lady whirled round, and snatched her skirts out of danger. The
+lad fled on the instant, scrambled up the high board-fence, and
+disappeared over it.
+
+His aunt Polly stood surprised a moment, and then broke into a gentle
+laugh.
+
+"Hang the boy, can't I never learn anything? Ain't he played me tricks
+enough like that for me to be looking out for him by this time? But old
+fools is the biggest fools there is. Can't learn an old dog new tricks,
+as the saying is. But my goodness, he never plays them alike, two days,
+and how is a body to know what's coming? He 'pears to know just how
+long he can torment me before I get my dander up, and he knows if he
+can make out to put me off for a minute or make me laugh, it's all down
+again and I can't hit him a lick. I ain't doing my duty by that boy,
+and that's the Lord's truth, goodness knows. Spare the rod and spile
+the child, as the Good Book says. I'm a laying up sin and suffering for
+us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
+own dead sister's boy, poor thing, and I ain't got the heart to lash
+him, somehow. Every time I let him off, my conscience does hurt me so,
+and every time I hit him my old heart most breaks. Well-a-well, man
+that is born of woman is of few days and full of trouble, as the
+Scripture says, and I reckon it's so. He'll play hookey this evening, *
+and [* Southwestern for "afternoon"] I'll just be obleeged to make him
+work, to-morrow, to punish him. It's mighty hard to make him work
+Saturdays, when all the boys is having holiday, but he hates work more
+than he hates anything else, and I've GOT to do some of my duty by him,
+or I'll be the ruination of the child."
+
+Tom did play hookey, and he had a very good time. He got back home
+barely in season to help Jim, the small colored boy, saw next-day's
+wood and split the kindlings before supper--at least he was there in
+time to tell his adventures to Jim while Jim did three-fourths of the
+work. Tom's younger brother (or rather half-brother) Sid was already
+through with his part of the work (picking up chips), for he was a
+quiet boy, and had no adventurous, troublesome ways.
+
+While Tom was eating his supper, and stealing sugar as opportunity
+offered, Aunt Polly asked him questions that were full of guile, and
+very deep--for she wanted to trap him into damaging revealments. Like
+many other simple-hearted souls, it was her pet vanity to believe she
+was endowed with a talent for dark and mysterious diplomacy, and she
+loved to contemplate her most transparent devices as marvels of low
+cunning. Said she:
+
+"Tom, it was middling warm in school, warn't it?"
+
+"Yes'm."
+
+"Powerful warm, warn't it?"
+
+"Yes'm."
+
+"Didn't you want to go in a-swimming, Tom?"
+
+A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
+He searched Aunt Polly's face, but it told him nothing. So he said:
+
+"No'm--well, not very much."
+
+The old lady reached out her hand and felt Tom's shirt, and said:
+
+"But you ain't too warm now, though." And it flattered her to reflect
+that she had discovered that the shirt was dry without anybody knowing
+that that was what she had in her mind. But in spite of her, Tom knew
+where the wind lay, now. So he forestalled what might be the next move:
+
+"Some of us pumped on our heads--mine's damp yet. See?"
+
+Aunt Polly was vexed to think she had overlooked that bit of
+circumstantial evidence, and missed a trick. Then she had a new
+inspiration:
+
+"Tom, you didn't have to undo your shirt collar where I sewed it, to
+pump on your head, did you? Unbutton your jacket!"
+
+The trouble vanished out of Tom's face. He opened his jacket. His
+shirt collar was securely sewed.
+
+"Bother! Well, go 'long with you. I'd made sure you'd played hookey
+and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
+singed cat, as the saying is--better'n you look. THIS time."
+
+She was half sorry her sagacity had miscarried, and half glad that Tom
+had stumbled into obedient conduct for once.
+
+But Sidney said:
+
+"Well, now, if I didn't think you sewed his collar with white thread,
+but it's black."
+
+"Why, I did sew it with white! Tom!"
+
+But Tom did not wait for the rest. As he went out at the door he said:
+
+"Siddy, I'll lick you for that."
+
+In a safe place Tom examined two large needles which were thrust into
+the lapels of his jacket, and had thread bound about them--one needle
+carried white thread and the other black. He said:
+
+"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
+she sews it with white, and sometimes she sews it with black. I wish to
+geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
+I bet you I'll lam Sid for that. I'll learn him!"
+
+He was not the Model Boy of the village. He knew the model boy very
+well though--and loathed him.
+
+Within two minutes, or even less, he had forgotten all his troubles.
+Not because his troubles were one whit less heavy and bitter to him
+than a man's are to a man, but because a new and powerful interest bore
+them down and drove them out of his mind for the time--just as men's
+misfortunes are forgotten in the excitement of new enterprises. This
+new interest was a valued novelty in whistling, which he had just
+acquired from a negro, and he was suffering to practise it undisturbed.
+It consisted in a peculiar bird-like turn, a sort of liquid warble,
+produced by touching the tongue to the roof of the mouth at short
+intervals in the midst of the music--the reader probably remembers how
+to do it, if he has ever been a boy. Diligence and attention soon gave
+him the knack of it, and he strode down the street with his mouth full
+of harmony and his soul full of gratitude. He felt much as an
+astronomer feels who has discovered a new planet--no doubt, as far as
+strong, deep, unalloyed pleasure is concerned, the advantage was with
+the boy, not the astronomer.
+
+The summer evenings were long. It was not dark, yet. Presently Tom
+checked his whistle. A stranger was before him--a boy a shade larger
+than himself. A new-comer of any age or either sex was an impressive
+curiosity in the poor little shabby village of St. Petersburg. This boy
+was well dressed, too--well dressed on a week-day. This was simply
+astounding. His cap was a dainty thing, his close-buttoned blue cloth
+roundabout was new and natty, and so were his pantaloons. He had shoes
+on--and it was only Friday. He even wore a necktie, a bright bit of
+ribbon. He had a citified air about him that ate into Tom's vitals. The
+more Tom stared at the splendid marvel, the higher he turned up his
+nose at his finery and the shabbier and shabbier his own outfit seemed
+to him to grow. Neither boy spoke. If one moved, the other moved--but
+only sidewise, in a circle; they kept face to face and eye to eye all
+the time. Finally Tom said:
+
+"I can lick you!"
+
+"I'd like to see you try it."
+
+"Well, I can do it."
+
+"No you can't, either."
+
+"Yes I can."
+
+"No you can't."
+
+"I can."
+
+"You can't."
+
+"Can!"
+
+"Can't!"
+
+An uncomfortable pause. Then Tom said:
+
+"What's your name?"
+
+"'Tisn't any of your business, maybe."
+
+"Well I 'low I'll MAKE it my business."
+
+"Well why don't you?"
+
+"If you say much, I will."
+
+"Much--much--MUCH. There now."
+
+"Oh, you think you're mighty smart, DON'T you? I could lick you with
+one hand tied behind me, if I wanted to."
+
+"Well why don't you DO it? You SAY you can do it."
+
+"Well I WILL, if you fool with me."
+
+"Oh yes--I've seen whole families in the same fix."
+
+"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
+
+"You can lump that hat if you don't like it. I dare you to knock it
+off--and anybody that'll take a dare will suck eggs."
+
+"You're a liar!"
+
+"You're another."
+
+"You're a fighting liar and dasn't take it up."
+
+"Aw--take a walk!"
+
+"Say--if you give me much more of your sass I'll take and bounce a
+rock off'n your head."
+
+"Oh, of COURSE you will."
+
+"Well I WILL."
+
+"Well why don't you DO it then? What do you keep SAYING you will for?
+Why don't you DO it? It's because you're afraid."
+
+"I AIN'T afraid."
+
+"You are."
+
+"I ain't."
+
+"You are."
+
+Another pause, and more eying and sidling around each other. Presently
+they were shoulder to shoulder. Tom said:
+
+"Get away from here!"
+
+"Go away yourself!"
+
+"I won't."
+
+"I won't either."
+
+So they stood, each with a foot placed at an angle as a brace, and
+both shoving with might and main, and glowering at each other with
+hate. But neither could get an advantage. After struggling till both
+were hot and flushed, each relaxed his strain with watchful caution,
+and Tom said:
+
+"You're a coward and a pup. I'll tell my big brother on you, and he
+can thrash you with his little finger, and I'll make him do it, too."
+
+"What do I care for your big brother? I've got a brother that's bigger
+than he is--and what's more, he can throw him over that fence, too."
+[Both brothers were imaginary.]
+
+"That's a lie."
+
+"YOUR saying so don't make it so."
+
+Tom drew a line in the dust with his big toe, and said:
+
+"I dare you to step over that, and I'll lick you till you can't stand
+up. Anybody that'll take a dare will steal sheep."
+
+The new boy stepped over promptly, and said:
+
+"Now you said you'd do it, now let's see you do it."
+
+"Don't you crowd me now; you better look out."
+
+"Well, you SAID you'd do it--why don't you do it?"
+
+"By jingo! for two cents I WILL do it."
+
+The new boy took two broad coppers out of his pocket and held them out
+with derision. Tom struck them to the ground. In an instant both boys
+were rolling and tumbling in the dirt, gripped together like cats; and
+for the space of a minute they tugged and tore at each other's hair and
+clothes, punched and scratched each other's nose, and covered
+themselves with dust and glory. Presently the confusion took form, and
+through the fog of battle Tom appeared, seated astride the new boy, and
+pounding him with his fists. "Holler 'nuff!" said he.
+
+The boy only struggled to free himself. He was crying--mainly from rage.
+
+"Holler 'nuff!"--and the pounding went on.
+
+At last the stranger got out a smothered "'Nuff!" and Tom let him up
+and said:
+
+"Now that'll learn you. Better look out who you're fooling with next
+time."
+
+The new boy went off brushing the dust from his clothes, sobbing,
+snuffling, and occasionally looking back and shaking his head and
+threatening what he would do to Tom the "next time he caught him out."
+To which Tom responded with jeers, and started off in high feather, and
+as soon as his back was turned the new boy snatched up a stone, threw
+it and hit him between the shoulders and then turned tail and ran like
+an antelope. Tom chased the traitor home, and thus found out where he
+lived. He then held a position at the gate for some time, daring the
+enemy to come outside, but the enemy only made faces at him through the
+window and declined. At last the enemy's mother appeared, and called
+Tom a bad, vicious, vulgar child, and ordered him away. So he went
+away; but he said he "'lowed" to "lay" for that boy.
+
+He got home pretty late that night, and when he climbed cautiously in
+at the window, he uncovered an ambuscade, in the person of his aunt;
+and when she saw the state his clothes were in her resolution to turn
+his Saturday holiday into captivity at hard labor became adamantine in
+its firmness.
+
+
+
+CHAPTER II
+
+SATURDAY morning was come, and all the summer world was bright and
+fresh, and brimming with life. There was a song in every heart; and if
+the heart was young the music issued at the lips. There was cheer in
+every face and a spring in every step. The locust-trees were in bloom
+and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
+the village and above it, was green with vegetation and it lay just far
+enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
+
+Tom appeared on the sidewalk with a bucket of whitewash and a
+long-handled brush. He surveyed the fence, and all gladness left him and
+a deep melancholy settled down upon his spirit. Thirty yards of board
+fence nine feet high. Life to him seemed hollow, and existence but a
+burden. Sighing, he dipped his brush and passed it along the topmost
+plank; repeated the operation; did it again; compared the insignificant
+whitewashed streak with the far-reaching continent of unwhitewashed
+fence, and sat down on a tree-box discouraged. Jim came skipping out at
+the gate with a tin pail, and singing Buffalo Gals. Bringing water from
+the town pump had always been hateful work in Tom's eyes, before, but
+now it did not strike him so. He remembered that there was company at
+the pump. White, mulatto, and negro boys and girls were always there
+waiting their turns, resting, trading playthings, quarrelling,
+fighting, skylarking. And he remembered that although the pump was only
+a hundred and fifty yards off, Jim never got back with a bucket of
+water under an hour--and even then somebody generally had to go after
+him. Tom said:
+
+"Say, Jim, I'll fetch the water if you'll whitewash some."
+
+Jim shook his head and said:
+
+"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
+water an' not stop foolin' roun' wid anybody. She say she spec' Mars
+Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
+to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
+
+"Oh, never you mind what she said, Jim. That's the way she always
+talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
+ever know."
+
+"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
+me. 'Deed she would."
+
+"SHE! She never licks anybody--whacks 'em over the head with her
+thimble--and who cares for that, I'd like to know. She talks awful, but
+talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
+a marvel. I'll give you a white alley!"
+
+Jim began to waver.
+
+"White alley, Jim! And it's a bully taw."
+
+"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
+'fraid ole missis--"
+
+"And besides, if you will I'll show you my sore toe."
+
+Jim was only human--this attraction was too much for him. He put down
+his pail, took the white alley, and bent over the toe with absorbing
+interest while the bandage was being unwound. In another moment he was
+flying down the street with his pail and a tingling rear, Tom was
+whitewashing with vigor, and Aunt Polly was retiring from the field
+with a slipper in her hand and triumph in her eye.
+
+But Tom's energy did not last. He began to think of the fun he had
+planned for this day, and his sorrows multiplied. Soon the free boys
+would come tripping along on all sorts of delicious expeditions, and
+they would make a world of fun of him for having to work--the very
+thought of it burnt him like fire. He got out his worldly wealth and
+examined it--bits of toys, marbles, and trash; enough to buy an
+exchange of WORK, maybe, but not half enough to buy so much as half an
+hour of pure freedom. So he returned his straitened means to his
+pocket, and gave up the idea of trying to buy the boys. At this dark
+and hopeless moment an inspiration burst upon him! Nothing less than a
+great, magnificent inspiration.
+
+He took up his brush and went tranquilly to work. Ben Rogers hove in
+sight presently--the very boy, of all boys, whose ridicule he had been
+dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
+heart was light and his anticipations high. He was eating an apple, and
+giving a long, melodious whoop, at intervals, followed by a deep-toned
+ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
+he drew near, he slackened speed, took the middle of the street, leaned
+far over to starboard and rounded to ponderously and with laborious
+pomp and circumstance--for he was personating the Big Missouri, and
+considered himself to be drawing nine feet of water. He was boat and
+captain and engine-bells combined, so he had to imagine himself
+standing on his own hurricane-deck giving the orders and executing them:
+
+"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
+drew up slowly toward the sidewalk.
+
+"Ship up to back! Ting-a-ling-ling!" His arms straightened and
+stiffened down his sides.
+
+"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
+Chow!" His right hand, meantime, describing stately circles--for it was
+representing a forty-foot wheel.
+
+"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
+The left hand began to describe circles.
+
+"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
+on the stabboard! Stop her! Let your outside turn over slow!
+Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
+Come--out with your spring-line--what're you about there! Take a turn
+round that stump with the bight of it! Stand by that stage, now--let her
+go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
+(trying the gauge-cocks).
+
+Tom went on whitewashing--paid no attention to the steamboat. Ben
+stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
+
+No answer. Tom surveyed his last touch with the eye of an artist, then
+he gave his brush another gentle sweep and surveyed the result, as
+before. Ben ranged up alongside of him. Tom's mouth watered for the
+apple, but he stuck to his work. Ben said:
+
+"Hello, old chap, you got to work, hey?"
+
+Tom wheeled suddenly and said:
+
+"Why, it's you, Ben! I warn't noticing."
+
+"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
+course you'd druther WORK--wouldn't you? Course you would!"
+
+Tom contemplated the boy a bit, and said:
+
+"What do you call work?"
+
+"Why, ain't THAT work?"
+
+Tom resumed his whitewashing, and answered carelessly:
+
+"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
+Sawyer."
+
+"Oh come, now, you don't mean to let on that you LIKE it?"
+
+The brush continued to move.
+
+"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
+a chance to whitewash a fence every day?"
+
+That put the thing in a new light. Ben stopped nibbling his apple. Tom
+swept his brush daintily back and forth--stepped back to note the
+effect--added a touch here and there--criticised the effect again--Ben
+watching every move and getting more and more interested, more and more
+absorbed. Presently he said:
+
+"Say, Tom, let ME whitewash a little."
+
+Tom considered, was about to consent; but he altered his mind:
+
+"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
+awful particular about this fence--right here on the street, you know
+--but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
+she's awful particular about this fence; it's got to be done very
+careful; I reckon there ain't one boy in a thousand, maybe two
+thousand, that can do it the way it's got to be done."
+
+"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
+let YOU, if you was me, Tom."
+
+"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
+do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
+let Sid. Now don't you see how I'm fixed? If you was to tackle this
+fence and anything was to happen to it--"
+
+"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
+you the core of my apple."
+
+"Well, here--No, Ben, now don't. I'm afeard--"
+
+"I'll give you ALL of it!"
+
+Tom gave up the brush with reluctance in his face, but alacrity in his
+heart. And while the late steamer Big Missouri worked and sweated in
+the sun, the retired artist sat on a barrel in the shade close by,
+dangled his legs, munched his apple, and planned the slaughter of more
+innocents. There was no lack of material; boys happened along every
+little while; they came to jeer, but remained to whitewash. By the time
+Ben was fagged out, Tom had traded the next chance to Billy Fisher for
+a kite, in good repair; and when he played out, Johnny Miller bought in
+for a dead rat and a string to swing it with--and so on, and so on,
+hour after hour. And when the middle of the afternoon came, from being
+a poor poverty-stricken boy in the morning, Tom was literally rolling
+in wealth. He had besides the things before mentioned, twelve marbles,
+part of a jews-harp, a piece of blue bottle-glass to look through, a
+spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
+a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
+fire-crackers, a kitten with only one eye, a brass doorknob, a
+dog-collar--but no dog--the handle of a knife, four pieces of
+orange-peel, and a dilapidated old window sash.
+
+He had had a nice, good, idle time all the while--plenty of company
+--and the fence had three coats of whitewash on it! If he hadn't run out
+of whitewash he would have bankrupted every boy in the village.
+
+Tom said to himself that it was not such a hollow world, after all. He
+had discovered a great law of human action, without knowing it--namely,
+that in order to make a man or a boy covet a thing, it is only
+necessary to make the thing difficult to attain. If he had been a great
+and wise philosopher, like the writer of this book, he would now have
+comprehended that Work consists of whatever a body is OBLIGED to do,
+and that Play consists of whatever a body is not obliged to do. And
+this would help him to understand why constructing artificial flowers
+or performing on a tread-mill is work, while rolling ten-pins or
+climbing Mont Blanc is only amusement. There are wealthy gentlemen in
+England who drive four-horse passenger-coaches twenty or thirty miles
+on a daily line, in the summer, because the privilege costs them
+considerable money; but if they were offered wages for the service,
+that would turn it into work and then they would resign.
+
+The boy mused awhile over the substantial change which had taken place
+in his worldly circumstances, and then wended toward headquarters to
+report.
+
+
+
+CHAPTER III
+
+TOM presented himself before Aunt Polly, who was sitting by an open
+window in a pleasant rearward apartment, which was bedroom,
+breakfast-room, dining-room, and library, combined. The balmy summer
+air, the restful quiet, the odor of the flowers, and the drowsing murmur
+of the bees had had their effect, and she was nodding over her knitting
+--for she had no company but the cat, and it was asleep in her lap. Her
+spectacles were propped up on her gray head for safety. She had thought
+that of course Tom had deserted long ago, and she wondered at seeing him
+place himself in her power again in this intrepid way. He said: "Mayn't
+I go and play now, aunt?"
+
+"What, a'ready? How much have you done?"
+
+"It's all done, aunt."
+
+"Tom, don't lie to me--I can't bear it."
+
+"I ain't, aunt; it IS all done."
+
+Aunt Polly placed small trust in such evidence. She went out to see
+for herself; and she would have been content to find twenty per cent.
+of Tom's statement true. When she found the entire fence whitewashed,
+and not only whitewashed but elaborately coated and recoated, and even
+a streak added to the ground, her astonishment was almost unspeakable.
+She said:
+
+"Well, I never! There's no getting round it, you can work when you're
+a mind to, Tom." And then she diluted the compliment by adding, "But
+it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
+and play; but mind you get back some time in a week, or I'll tan you."
+
+She was so overcome by the splendor of his achievement that she took
+him into the closet and selected a choice apple and delivered it to
+him, along with an improving lecture upon the added value and flavor a
+treat took to itself when it came without sin through virtuous effort.
+And while she closed with a happy Scriptural flourish, he "hooked" a
+doughnut.
+
+Then he skipped out, and saw Sid just starting up the outside stairway
+that led to the back rooms on the second floor. Clods were handy and
+the air was full of them in a twinkling. They raged around Sid like a
+hail-storm; and before Aunt Polly could collect her surprised faculties
+and sally to the rescue, six or seven clods had taken personal effect,
+and Tom was over the fence and gone. There was a gate, but as a general
+thing he was too crowded for time to make use of it. His soul was at
+peace, now that he had settled with Sid for calling attention to his
+black thread and getting him into trouble.
+
+Tom skirted the block, and came round into a muddy alley that led by
+the back of his aunt's cow-stable. He presently got safely beyond the
+reach of capture and punishment, and hastened toward the public square
+of the village, where two "military" companies of boys had met for
+conflict, according to previous appointment. Tom was General of one of
+these armies, Joe Harper (a bosom friend) General of the other. These
+two great commanders did not condescend to fight in person--that being
+better suited to the still smaller fry--but sat together on an eminence
+and conducted the field operations by orders delivered through
+aides-de-camp. Tom's army won a great victory, after a long and
+hard-fought battle. Then the dead were counted, prisoners exchanged,
+the terms of the next disagreement agreed upon, and the day for the
+necessary battle appointed; after which the armies fell into line and
+marched away, and Tom turned homeward alone.
+
+As he was passing by the house where Jeff Thatcher lived, he saw a new
+girl in the garden--a lovely little blue-eyed creature with yellow hair
+plaited into two long-tails, white summer frock and embroidered
+pantalettes. The fresh-crowned hero fell without firing a shot. A
+certain Amy Lawrence vanished out of his heart and left not even a
+memory of herself behind. He had thought he loved her to distraction;
+he had regarded his passion as adoration; and behold it was only a poor
+little evanescent partiality. He had been months winning her; she had
+confessed hardly a week ago; he had been the happiest and the proudest
+boy in the world only seven short days, and here in one instant of time
+she had gone out of his heart like a casual stranger whose visit is
+done.
+
+He worshipped this new angel with furtive eye, till he saw that she
+had discovered him; then he pretended he did not know she was present,
+and began to "show off" in all sorts of absurd boyish ways, in order to
+win her admiration. He kept up this grotesque foolishness for some
+time; but by-and-by, while he was in the midst of some dangerous
+gymnastic performances, he glanced aside and saw that the little girl
+was wending her way toward the house. Tom came up to the fence and
+leaned on it, grieving, and hoping she would tarry yet awhile longer.
+She halted a moment on the steps and then moved toward the door. Tom
+heaved a great sigh as she put her foot on the threshold. But his face
+lit up, right away, for she tossed a pansy over the fence a moment
+before she disappeared.
+
+The boy ran around and stopped within a foot or two of the flower, and
+then shaded his eyes with his hand and began to look down street as if
+he had discovered something of interest going on in that direction.
+Presently he picked up a straw and began trying to balance it on his
+nose, with his head tilted far back; and as he moved from side to side,
+in his efforts, he edged nearer and nearer toward the pansy; finally
+his bare foot rested upon it, his pliant toes closed upon it, and he
+hopped away with the treasure and disappeared round the corner. But
+only for a minute--only while he could button the flower inside his
+jacket, next his heart--or next his stomach, possibly, for he was not
+much posted in anatomy, and not hypercritical, anyway.
+
+He returned, now, and hung about the fence till nightfall, "showing
+off," as before; but the girl never exhibited herself again, though Tom
+comforted himself a little with the hope that she had been near some
+window, meantime, and been aware of his attentions. Finally he strode
+home reluctantly, with his poor head full of visions.
+
+All through supper his spirits were so high that his aunt wondered
+"what had got into the child." He took a good scolding about clodding
+Sid, and did not seem to mind it in the least. He tried to steal sugar
+under his aunt's very nose, and got his knuckles rapped for it. He said:
+
+"Aunt, you don't whack Sid when he takes it."
+
+"Well, Sid don't torment a body the way you do. You'd be always into
+that sugar if I warn't watching you."
+
+Presently she stepped into the kitchen, and Sid, happy in his
+immunity, reached for the sugar-bowl--a sort of glorying over Tom which
+was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
+and broke. Tom was in ecstasies. In such ecstasies that he even
+controlled his tongue and was silent. He said to himself that he would
+not speak a word, even when his aunt came in, but would sit perfectly
+still till she asked who did the mischief; and then he would tell, and
+there would be nothing so good in the world as to see that pet model
+"catch it." He was so brimful of exultation that he could hardly hold
+himself when the old lady came back and stood above the wreck
+discharging lightnings of wrath from over her spectacles. He said to
+himself, "Now it's coming!" And the next instant he was sprawling on
+the floor! The potent palm was uplifted to strike again when Tom cried
+out:
+
+"Hold on, now, what 'er you belting ME for?--Sid broke it!"
+
+Aunt Polly paused, perplexed, and Tom looked for healing pity. But
+when she got her tongue again, she only said:
+
+"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
+other audacious mischief when I wasn't around, like enough."
+
+Then her conscience reproached her, and she yearned to say something
+kind and loving; but she judged that this would be construed into a
+confession that she had been in the wrong, and discipline forbade that.
+So she kept silence, and went about her affairs with a troubled heart.
+Tom sulked in a corner and exalted his woes. He knew that in her heart
+his aunt was on her knees to him, and he was morosely gratified by the
+consciousness of it. He would hang out no signals, he would take notice
+of none. He knew that a yearning glance fell upon him, now and then,
+through a film of tears, but he refused recognition of it. He pictured
+himself lying sick unto death and his aunt bending over him beseeching
+one little forgiving word, but he would turn his face to the wall, and
+die with that word unsaid. Ah, how would she feel then? And he pictured
+himself brought home from the river, dead, with his curls all wet, and
+his sore heart at rest. How she would throw herself upon him, and how
+her tears would fall like rain, and her lips pray God to give her back
+her boy and she would never, never abuse him any more! But he would lie
+there cold and white and make no sign--a poor little sufferer, whose
+griefs were at an end. He so worked upon his feelings with the pathos
+of these dreams, that he had to keep swallowing, he was so like to
+choke; and his eyes swam in a blur of water, which overflowed when he
+winked, and ran down and trickled from the end of his nose. And such a
+luxury to him was this petting of his sorrows, that he could not bear
+to have any worldly cheeriness or any grating delight intrude upon it;
+it was too sacred for such contact; and so, presently, when his cousin
+Mary danced in, all alive with the joy of seeing home again after an
+age-long visit of one week to the country, he got up and moved in
+clouds and darkness out at one door as she brought song and sunshine in
+at the other.
+
+He wandered far from the accustomed haunts of boys, and sought
+desolate places that were in harmony with his spirit. A log raft in the
+river invited him, and he seated himself on its outer edge and
+contemplated the dreary vastness of the stream, wishing, the while,
+that he could only be drowned, all at once and unconsciously, without
+undergoing the uncomfortable routine devised by nature. Then he thought
+of his flower. He got it out, rumpled and wilted, and it mightily
+increased his dismal felicity. He wondered if she would pity him if she
+knew? Would she cry, and wish that she had a right to put her arms
+around his neck and comfort him? Or would she turn coldly away like all
+the hollow world? This picture brought such an agony of pleasurable
+suffering that he worked it over and over again in his mind and set it
+up in new and varied lights, till he wore it threadbare. At last he
+rose up sighing and departed in the darkness.
+
+About half-past nine or ten o'clock he came along the deserted street
+to where the Adored Unknown lived; he paused a moment; no sound fell
+upon his listening ear; a candle was casting a dull glow upon the
+curtain of a second-story window. Was the sacred presence there? He
+climbed the fence, threaded his stealthy way through the plants, till
+he stood under that window; he looked up at it long, and with emotion;
+then he laid him down on the ground under it, disposing himself upon
+his back, with his hands clasped upon his breast and holding his poor
+wilted flower. And thus he would die--out in the cold world, with no
+shelter over his homeless head, no friendly hand to wipe the
+death-damps from his brow, no loving face to bend pityingly over him
+when the great agony came. And thus SHE would see him when she looked
+out upon the glad morning, and oh! would she drop one little tear upon
+his poor, lifeless form, would she heave one little sigh to see a bright
+young life so rudely blighted, so untimely cut down?
+
+The window went up, a maid-servant's discordant voice profaned the
+holy calm, and a deluge of water drenched the prone martyr's remains!
+
+The strangling hero sprang up with a relieving snort. There was a whiz
+as of a missile in the air, mingled with the murmur of a curse, a sound
+as of shivering glass followed, and a small, vague form went over the
+fence and shot away in the gloom.
+
+Not long after, as Tom, all undressed for bed, was surveying his
+drenched garments by the light of a tallow dip, Sid woke up; but if he
+had any dim idea of making any "references to allusions," he thought
+better of it and held his peace, for there was danger in Tom's eye.
+
+Tom turned in without the added vexation of prayers, and Sid made
+mental note of the omission.
+
+
+
+CHAPTER IV
+
+THE sun rose upon a tranquil world, and beamed down upon the peaceful
+village like a benediction. Breakfast over, Aunt Polly had family
+worship: it began with a prayer built from the ground up of solid
+courses of Scriptural quotations, welded together with a thin mortar of
+originality; and from the summit of this she delivered a grim chapter
+of the Mosaic Law, as from Sinai.
+
+Then Tom girded up his loins, so to speak, and went to work to "get
+his verses." Sid had learned his lesson days before. Tom bent all his
+energies to the memorizing of five verses, and he chose part of the
+Sermon on the Mount, because he could find no verses that were shorter.
+At the end of half an hour Tom had a vague general idea of his lesson,
+but no more, for his mind was traversing the whole field of human
+thought, and his hands were busy with distracting recreations. Mary
+took his book to hear him recite, and he tried to find his way through
+the fog:
+
+"Blessed are the--a--a--"
+
+"Poor"--
+
+"Yes--poor; blessed are the poor--a--a--"
+
+"In spirit--"
+
+"In spirit; blessed are the poor in spirit, for they--they--"
+
+"THEIRS--"
+
+"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
+of heaven. Blessed are they that mourn, for they--they--"
+
+"Sh--"
+
+"For they--a--"
+
+"S, H, A--"
+
+"For they S, H--Oh, I don't know what it is!"
+
+"SHALL!"
+
+"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
+blessed are they that shall--they that--a--they that shall mourn, for
+they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
+want to be so mean for?"
+
+"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
+do that. You must go and learn it again. Don't you be discouraged, Tom,
+you'll manage it--and if you do, I'll give you something ever so nice.
+There, now, that's a good boy."
+
+"All right! What is it, Mary, tell me what it is."
+
+"Never you mind, Tom. You know if I say it's nice, it is nice."
+
+"You bet you that's so, Mary. All right, I'll tackle it again."
+
+And he did "tackle it again"--and under the double pressure of
+curiosity and prospective gain he did it with such spirit that he
+accomplished a shining success. Mary gave him a brand-new "Barlow"
+knife worth twelve and a half cents; and the convulsion of delight that
+swept his system shook him to his foundations. True, the knife would
+not cut anything, but it was a "sure-enough" Barlow, and there was
+inconceivable grandeur in that--though where the Western boys ever got
+the idea that such a weapon could possibly be counterfeited to its
+injury is an imposing mystery and will always remain so, perhaps. Tom
+contrived to scarify the cupboard with it, and was arranging to begin
+on the bureau, when he was called off to dress for Sunday-school.
+
+Mary gave him a tin basin of water and a piece of soap, and he went
+outside the door and set the basin on a little bench there; then he
+dipped the soap in the water and laid it down; turned up his sleeves;
+poured out the water on the ground, gently, and then entered the
+kitchen and began to wipe his face diligently on the towel behind the
+door. But Mary removed the towel and said:
+
+"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
+you."
+
+Tom was a trifle disconcerted. The basin was refilled, and this time
+he stood over it a little while, gathering resolution; took in a big
+breath and began. When he entered the kitchen presently, with both eyes
+shut and groping for the towel with his hands, an honorable testimony
+of suds and water was dripping from his face. But when he emerged from
+the towel, he was not yet satisfactory, for the clean territory stopped
+short at his chin and his jaws, like a mask; below and beyond this line
+there was a dark expanse of unirrigated soil that spread downward in
+front and backward around his neck. Mary took him in hand, and when she
+was done with him he was a man and a brother, without distinction of
+color, and his saturated hair was neatly brushed, and its short curls
+wrought into a dainty and symmetrical general effect. [He privately
+smoothed out the curls, with labor and difficulty, and plastered his
+hair close down to his head; for he held curls to be effeminate, and
+his own filled his life with bitterness.] Then Mary got out a suit of
+his clothing that had been used only on Sundays during two years--they
+were simply called his "other clothes"--and so by that we know the
+size of his wardrobe. The girl "put him to rights" after he had dressed
+himself; she buttoned his neat roundabout up to his chin, turned his
+vast shirt collar down over his shoulders, brushed him off and crowned
+him with his speckled straw hat. He now looked exceedingly improved and
+uncomfortable. He was fully as uncomfortable as he looked; for there
+was a restraint about whole clothes and cleanliness that galled him. He
+hoped that Mary would forget his shoes, but the hope was blighted; she
+coated them thoroughly with tallow, as was the custom, and brought them
+out. He lost his temper and said he was always being made to do
+everything he didn't want to do. But Mary said, persuasively:
+
+"Please, Tom--that's a good boy."
+
+So he got into the shoes snarling. Mary was soon ready, and the three
+children set out for Sunday-school--a place that Tom hated with his
+whole heart; but Sid and Mary were fond of it.
+
+Sabbath-school hours were from nine to half-past ten; and then church
+service. Two of the children always remained for the sermon
+voluntarily, and the other always remained too--for stronger reasons.
+The church's high-backed, uncushioned pews would seat about three
+hundred persons; the edifice was but a small, plain affair, with a sort
+of pine board tree-box on top of it for a steeple. At the door Tom
+dropped back a step and accosted a Sunday-dressed comrade:
+
+"Say, Billy, got a yaller ticket?"
+
+"Yes."
+
+"What'll you take for her?"
+
+"What'll you give?"
+
+"Piece of lickrish and a fish-hook."
+
+"Less see 'em."
+
+Tom exhibited. They were satisfactory, and the property changed hands.
+Then Tom traded a couple of white alleys for three red tickets, and
+some small trifle or other for a couple of blue ones. He waylaid other
+boys as they came, and went on buying tickets of various colors ten or
+fifteen minutes longer. He entered the church, now, with a swarm of
+clean and noisy boys and girls, proceeded to his seat and started a
+quarrel with the first boy that came handy. The teacher, a grave,
+elderly man, interfered; then turned his back a moment and Tom pulled a
+boy's hair in the next bench, and was absorbed in his book when the boy
+turned around; stuck a pin in another boy, presently, in order to hear
+him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
+class were of a pattern--restless, noisy, and troublesome. When they
+came to recite their lessons, not one of them knew his verses
+perfectly, but had to be prompted all along. However, they worried
+through, and each got his reward--in small blue tickets, each with a
+passage of Scripture on it; each blue ticket was pay for two verses of
+the recitation. Ten blue tickets equalled a red one, and could be
+exchanged for it; ten red tickets equalled a yellow one; for ten yellow
+tickets the superintendent gave a very plainly bound Bible (worth forty
+cents in those easy times) to the pupil. How many of my readers would
+have the industry and application to memorize two thousand verses, even
+for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
+was the patient work of two years--and a boy of German parentage had
+won four or five. He once recited three thousand verses without
+stopping; but the strain upon his mental faculties was too great, and
+he was little better than an idiot from that day forth--a grievous
+misfortune for the school, for on great occasions, before company, the
+superintendent (as Tom expressed it) had always made this boy come out
+and "spread himself." Only the older pupils managed to keep their
+tickets and stick to their tedious work long enough to get a Bible, and
+so the delivery of one of these prizes was a rare and noteworthy
+circumstance; the successful pupil was so great and conspicuous for
+that day that on the spot every scholar's heart was fired with a fresh
+ambition that often lasted a couple of weeks. It is possible that Tom's
+mental stomach had never really hungered for one of those prizes, but
+unquestionably his entire being had for many a day longed for the glory
+and the eclat that came with it.
+
+In due course the superintendent stood up in front of the pulpit, with
+a closed hymn-book in his hand and his forefinger inserted between its
+leaves, and commanded attention. When a Sunday-school superintendent
+makes his customary little speech, a hymn-book in the hand is as
+necessary as is the inevitable sheet of music in the hand of a singer
+who stands forward on the platform and sings a solo at a concert
+--though why, is a mystery: for neither the hymn-book nor the sheet of
+music is ever referred to by the sufferer. This superintendent was a
+slim creature of thirty-five, with a sandy goatee and short sandy hair;
+he wore a stiff standing-collar whose upper edge almost reached his
+ears and whose sharp points curved forward abreast the corners of his
+mouth--a fence that compelled a straight lookout ahead, and a turning
+of the whole body when a side view was required; his chin was propped
+on a spreading cravat which was as broad and as long as a bank-note,
+and had fringed ends; his boot toes were turned sharply up, in the
+fashion of the day, like sleigh-runners--an effect patiently and
+laboriously produced by the young men by sitting with their toes
+pressed against a wall for hours together. Mr. Walters was very earnest
+of mien, and very sincere and honest at heart; and he held sacred
+things and places in such reverence, and so separated them from worldly
+matters, that unconsciously to himself his Sunday-school voice had
+acquired a peculiar intonation which was wholly absent on week-days. He
+began after this fashion:
+
+"Now, children, I want you all to sit up just as straight and pretty
+as you can and give me all your attention for a minute or two. There
+--that is it. That is the way good little boys and girls should do. I see
+one little girl who is looking out of the window--I am afraid she
+thinks I am out there somewhere--perhaps up in one of the trees making
+a speech to the little birds. [Applausive titter.] I want to tell you
+how good it makes me feel to see so many bright, clean little faces
+assembled in a place like this, learning to do right and be good." And
+so forth and so on. It is not necessary to set down the rest of the
+oration. It was of a pattern which does not vary, and so it is familiar
+to us all.
+
+The latter third of the speech was marred by the resumption of fights
+and other recreations among certain of the bad boys, and by fidgetings
+and whisperings that extended far and wide, washing even to the bases
+of isolated and incorruptible rocks like Sid and Mary. But now every
+sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
+the conclusion of the speech was received with a burst of silent
+gratitude.
+
+A good part of the whispering had been occasioned by an event which
+was more or less rare--the entrance of visitors: lawyer Thatcher,
+accompanied by a very feeble and aged man; a fine, portly, middle-aged
+gentleman with iron-gray hair; and a dignified lady who was doubtless
+the latter's wife. The lady was leading a child. Tom had been restless
+and full of chafings and repinings; conscience-smitten, too--he could
+not meet Amy Lawrence's eye, he could not brook her loving gaze. But
+when he saw this small new-comer his soul was all ablaze with bliss in
+a moment. The next moment he was "showing off" with all his might
+--cuffing boys, pulling hair, making faces--in a word, using every art
+that seemed likely to fascinate a girl and win her applause. His
+exaltation had but one alloy--the memory of his humiliation in this
+angel's garden--and that record in sand was fast washing out, under
+the waves of happiness that were sweeping over it now.
+
+The visitors were given the highest seat of honor, and as soon as Mr.
+Walters' speech was finished, he introduced them to the school. The
+middle-aged man turned out to be a prodigious personage--no less a one
+than the county judge--altogether the most august creation these
+children had ever looked upon--and they wondered what kind of material
+he was made of--and they half wanted to hear him roar, and were half
+afraid he might, too. He was from Constantinople, twelve miles away--so
+he had travelled, and seen the world--these very eyes had looked upon
+the county court-house--which was said to have a tin roof. The awe
+which these reflections inspired was attested by the impressive silence
+and the ranks of staring eyes. This was the great Judge Thatcher,
+brother of their own lawyer. Jeff Thatcher immediately went forward, to
+be familiar with the great man and be envied by the school. It would
+have been music to his soul to hear the whisperings:
+
+"Look at him, Jim! He's a going up there. Say--look! he's a going to
+shake hands with him--he IS shaking hands with him! By jings, don't you
+wish you was Jeff?"
+
+Mr. Walters fell to "showing off," with all sorts of official
+bustlings and activities, giving orders, delivering judgments,
+discharging directions here, there, everywhere that he could find a
+target. The librarian "showed off"--running hither and thither with his
+arms full of books and making a deal of the splutter and fuss that
+insect authority delights in. The young lady teachers "showed off"
+--bending sweetly over pupils that were lately being boxed, lifting
+pretty warning fingers at bad little boys and patting good ones
+lovingly. The young gentlemen teachers "showed off" with small
+scoldings and other little displays of authority and fine attention to
+discipline--and most of the teachers, of both sexes, found business up
+at the library, by the pulpit; and it was business that frequently had
+to be done over again two or three times (with much seeming vexation).
+The little girls "showed off" in various ways, and the little boys
+"showed off" with such diligence that the air was thick with paper wads
+and the murmur of scufflings. And above it all the great man sat and
+beamed a majestic judicial smile upon all the house, and warmed himself
+in the sun of his own grandeur--for he was "showing off," too.
+
+There was only one thing wanting to make Mr. Walters' ecstasy
+complete, and that was a chance to deliver a Bible-prize and exhibit a
+prodigy. Several pupils had a few yellow tickets, but none had enough
+--he had been around among the star pupils inquiring. He would have given
+worlds, now, to have that German lad back again with a sound mind.
+
+And now at this moment, when hope was dead, Tom Sawyer came forward
+with nine yellow tickets, nine red tickets, and ten blue ones, and
+demanded a Bible. This was a thunderbolt out of a clear sky. Walters
+was not expecting an application from this source for the next ten
+years. But there was no getting around it--here were the certified
+checks, and they were good for their face. Tom was therefore elevated
+to a place with the Judge and the other elect, and the great news was
+announced from headquarters. It was the most stunning surprise of the
+decade, and so profound was the sensation that it lifted the new hero
+up to the judicial one's altitude, and the school had two marvels to
+gaze upon in place of one. The boys were all eaten up with envy--but
+those that suffered the bitterest pangs were those who perceived too
+late that they themselves had contributed to this hated splendor by
+trading tickets to Tom for the wealth he had amassed in selling
+whitewashing privileges. These despised themselves, as being the dupes
+of a wily fraud, a guileful snake in the grass.
+
+The prize was delivered to Tom with as much effusion as the
+superintendent could pump up under the circumstances; but it lacked
+somewhat of the true gush, for the poor fellow's instinct taught him
+that there was a mystery here that could not well bear the light,
+perhaps; it was simply preposterous that this boy had warehoused two
+thousand sheaves of Scriptural wisdom on his premises--a dozen would
+strain his capacity, without a doubt.
+
+Amy Lawrence was proud and glad, and she tried to make Tom see it in
+her face--but he wouldn't look. She wondered; then she was just a grain
+troubled; next a dim suspicion came and went--came again; she watched;
+a furtive glance told her worlds--and then her heart broke, and she was
+jealous, and angry, and the tears came and she hated everybody. Tom
+most of all (she thought).
+
+Tom was introduced to the Judge; but his tongue was tied, his breath
+would hardly come, his heart quaked--partly because of the awful
+greatness of the man, but mainly because he was her parent. He would
+have liked to fall down and worship him, if it were in the dark. The
+Judge put his hand on Tom's head and called him a fine little man, and
+asked him what his name was. The boy stammered, gasped, and got it out:
+
+"Tom."
+
+"Oh, no, not Tom--it is--"
+
+"Thomas."
+
+"Ah, that's it. I thought there was more to it, maybe. That's very
+well. But you've another one I daresay, and you'll tell it to me, won't
+you?"
+
+"Tell the gentleman your other name, Thomas," said Walters, "and say
+sir. You mustn't forget your manners."
+
+"Thomas Sawyer--sir."
+
+"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
+Two thousand verses is a great many--very, very great many. And you
+never can be sorry for the trouble you took to learn them; for
+knowledge is worth more than anything there is in the world; it's what
+makes great men and good men; you'll be a great man and a good man
+yourself, some day, Thomas, and then you'll look back and say, It's all
+owing to the precious Sunday-school privileges of my boyhood--it's all
+owing to my dear teachers that taught me to learn--it's all owing to
+the good superintendent, who encouraged me, and watched over me, and
+gave me a beautiful Bible--a splendid elegant Bible--to keep and have
+it all for my own, always--it's all owing to right bringing up! That is
+what you will say, Thomas--and you wouldn't take any money for those
+two thousand verses--no indeed you wouldn't. And now you wouldn't mind
+telling me and this lady some of the things you've learned--no, I know
+you wouldn't--for we are proud of little boys that learn. Now, no
+doubt you know the names of all the twelve disciples. Won't you tell us
+the names of the first two that were appointed?"
+
+Tom was tugging at a button-hole and looking sheepish. He blushed,
+now, and his eyes fell. Mr. Walters' heart sank within him. He said to
+himself, it is not possible that the boy can answer the simplest
+question--why DID the Judge ask him? Yet he felt obliged to speak up
+and say:
+
+"Answer the gentleman, Thomas--don't be afraid."
+
+Tom still hung fire.
+
+"Now I know you'll tell me," said the lady. "The names of the first
+two disciples were--"
+
+"DAVID AND GOLIAH!"
+
+Let us draw the curtain of charity over the rest of the scene.
+
+
+
+CHAPTER V
+
+ABOUT half-past ten the cracked bell of the small church began to
+ring, and presently the people began to gather for the morning sermon.
+The Sunday-school children distributed themselves about the house and
+occupied pews with their parents, so as to be under supervision. Aunt
+Polly came, and Tom and Sid and Mary sat with her--Tom being placed
+next the aisle, in order that he might be as far away from the open
+window and the seductive outside summer scenes as possible. The crowd
+filed up the aisles: the aged and needy postmaster, who had seen better
+days; the mayor and his wife--for they had a mayor there, among other
+unnecessaries; the justice of the peace; the widow Douglass, fair,
+smart, and forty, a generous, good-hearted soul and well-to-do, her
+hill mansion the only palace in the town, and the most hospitable and
+much the most lavish in the matter of festivities that St. Petersburg
+could boast; the bent and venerable Major and Mrs. Ward; lawyer
+Riverson, the new notable from a distance; next the belle of the
+village, followed by a troop of lawn-clad and ribbon-decked young
+heart-breakers; then all the young clerks in town in a body--for they
+had stood in the vestibule sucking their cane-heads, a circling wall of
+oiled and simpering admirers, till the last girl had run their gantlet;
+and last of all came the Model Boy, Willie Mufferson, taking as heedful
+care of his mother as if she were cut glass. He always brought his
+mother to church, and was the pride of all the matrons. The boys all
+hated him, he was so good. And besides, he had been "thrown up to them"
+so much. His white handkerchief was hanging out of his pocket behind, as
+usual on Sundays--accidentally. Tom had no handkerchief, and he looked
+upon boys who had as snobs.
+
+The congregation being fully assembled, now, the bell rang once more,
+to warn laggards and stragglers, and then a solemn hush fell upon the
+church which was only broken by the tittering and whispering of the
+choir in the gallery. The choir always tittered and whispered all
+through service. There was once a church choir that was not ill-bred,
+but I have forgotten where it was, now. It was a great many years ago,
+and I can scarcely remember anything about it, but I think it was in
+some foreign country.
+
+The minister gave out the hymn, and read it through with a relish, in
+a peculiar style which was much admired in that part of the country.
+His voice began on a medium key and climbed steadily up till it reached
+a certain point, where it bore with strong emphasis upon the topmost
+word and then plunged down as if from a spring-board:
+
+ Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
+
+ Whilst others fight to win the prize, and sail thro' BLOODY seas?
+
+He was regarded as a wonderful reader. At church "sociables" he was
+always called upon to read poetry; and when he was through, the ladies
+would lift up their hands and let them fall helplessly in their laps,
+and "wall" their eyes, and shake their heads, as much as to say, "Words
+cannot express it; it is too beautiful, TOO beautiful for this mortal
+earth."
+
+After the hymn had been sung, the Rev. Mr. Sprague turned himself into
+a bulletin-board, and read off "notices" of meetings and societies and
+things till it seemed that the list would stretch out to the crack of
+doom--a queer custom which is still kept up in America, even in cities,
+away here in this age of abundant newspapers. Often, the less there is
+to justify a traditional custom, the harder it is to get rid of it.
+
+And now the minister prayed. A good, generous prayer it was, and went
+into details: it pleaded for the church, and the little children of the
+church; for the other churches of the village; for the village itself;
+for the county; for the State; for the State officers; for the United
+States; for the churches of the United States; for Congress; for the
+President; for the officers of the Government; for poor sailors, tossed
+by stormy seas; for the oppressed millions groaning under the heel of
+European monarchies and Oriental despotisms; for such as have the light
+and the good tidings, and yet have not eyes to see nor ears to hear
+withal; for the heathen in the far islands of the sea; and closed with
+a supplication that the words he was about to speak might find grace
+and favor, and be as seed sown in fertile ground, yielding in time a
+grateful harvest of good. Amen.
+
+There was a rustling of dresses, and the standing congregation sat
+down. The boy whose history this book relates did not enjoy the prayer,
+he only endured it--if he even did that much. He was restive all
+through it; he kept tally of the details of the prayer, unconsciously
+--for he was not listening, but he knew the ground of old, and the
+clergyman's regular route over it--and when a little trifle of new
+matter was interlarded, his ear detected it and his whole nature
+resented it; he considered additions unfair, and scoundrelly. In the
+midst of the prayer a fly had lit on the back of the pew in front of
+him and tortured his spirit by calmly rubbing its hands together,
+embracing its head with its arms, and polishing it so vigorously that
+it seemed to almost part company with the body, and the slender thread
+of a neck was exposed to view; scraping its wings with its hind legs
+and smoothing them to its body as if they had been coat-tails; going
+through its whole toilet as tranquilly as if it knew it was perfectly
+safe. As indeed it was; for as sorely as Tom's hands itched to grab for
+it they did not dare--he believed his soul would be instantly destroyed
+if he did such a thing while the prayer was going on. But with the
+closing sentence his hand began to curve and steal forward; and the
+instant the "Amen" was out the fly was a prisoner of war. His aunt
+detected the act and made him let it go.
+
+The minister gave out his text and droned along monotonously through
+an argument that was so prosy that many a head by and by began to nod
+--and yet it was an argument that dealt in limitless fire and brimstone
+and thinned the predestined elect down to a company so small as to be
+hardly worth the saving. Tom counted the pages of the sermon; after
+church he always knew how many pages there had been, but he seldom knew
+anything else about the discourse. However, this time he was really
+interested for a little while. The minister made a grand and moving
+picture of the assembling together of the world's hosts at the
+millennium when the lion and the lamb should lie down together and a
+little child should lead them. But the pathos, the lesson, the moral of
+the great spectacle were lost upon the boy; he only thought of the
+conspicuousness of the principal character before the on-looking
+nations; his face lit with the thought, and he said to himself that he
+wished he could be that child, if it was a tame lion.
+
+Now he lapsed into suffering again, as the dry argument was resumed.
+Presently he bethought him of a treasure he had and got it out. It was
+a large black beetle with formidable jaws--a "pinchbug," he called it.
+It was in a percussion-cap box. The first thing the beetle did was to
+take him by the finger. A natural fillip followed, the beetle went
+floundering into the aisle and lit on its back, and the hurt finger
+went into the boy's mouth. The beetle lay there working its helpless
+legs, unable to turn over. Tom eyed it, and longed for it; but it was
+safe out of his reach. Other people uninterested in the sermon found
+relief in the beetle, and they eyed it too. Presently a vagrant poodle
+dog came idling along, sad at heart, lazy with the summer softness and
+the quiet, weary of captivity, sighing for change. He spied the beetle;
+the drooping tail lifted and wagged. He surveyed the prize; walked
+around it; smelt at it from a safe distance; walked around it again;
+grew bolder, and took a closer smell; then lifted his lip and made a
+gingerly snatch at it, just missing it; made another, and another;
+began to enjoy the diversion; subsided to his stomach with the beetle
+between his paws, and continued his experiments; grew weary at last,
+and then indifferent and absent-minded. His head nodded, and little by
+little his chin descended and touched the enemy, who seized it. There
+was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
+couple of yards away, and lit on its back once more. The neighboring
+spectators shook with a gentle inward joy, several faces went behind
+fans and handkerchiefs, and Tom was entirely happy. The dog looked
+foolish, and probably felt so; but there was resentment in his heart,
+too, and a craving for revenge. So he went to the beetle and began a
+wary attack on it again; jumping at it from every point of a circle,
+lighting with his fore-paws within an inch of the creature, making even
+closer snatches at it with his teeth, and jerking his head till his
+ears flapped again. But he grew tired once more, after a while; tried
+to amuse himself with a fly but found no relief; followed an ant
+around, with his nose close to the floor, and quickly wearied of that;
+yawned, sighed, forgot the beetle entirely, and sat down on it. Then
+there was a wild yelp of agony and the poodle went sailing up the
+aisle; the yelps continued, and so did the dog; he crossed the house in
+front of the altar; he flew down the other aisle; he crossed before the
+doors; he clamored up the home-stretch; his anguish grew with his
+progress, till presently he was but a woolly comet moving in its orbit
+with the gleam and the speed of light. At last the frantic sufferer
+sheered from its course, and sprang into its master's lap; he flung it
+out of the window, and the voice of distress quickly thinned away and
+died in the distance.
+
+By this time the whole church was red-faced and suffocating with
+suppressed laughter, and the sermon had come to a dead standstill. The
+discourse was resumed presently, but it went lame and halting, all
+possibility of impressiveness being at an end; for even the gravest
+sentiments were constantly being received with a smothered burst of
+unholy mirth, under cover of some remote pew-back, as if the poor
+parson had said a rarely facetious thing. It was a genuine relief to
+the whole congregation when the ordeal was over and the benediction
+pronounced.
+
+Tom Sawyer went home quite cheerful, thinking to himself that there
+was some satisfaction about divine service when there was a bit of
+variety in it. He had but one marring thought; he was willing that the
+dog should play with his pinchbug, but he did not think it was upright
+in him to carry it off.
+
+
+
+CHAPTER VI
+
+MONDAY morning found Tom Sawyer miserable. Monday morning always found
+him so--because it began another week's slow suffering in school. He
+generally began that day with wishing he had had no intervening
+holiday, it made the going into captivity and fetters again so much
+more odious.
+
+Tom lay thinking. Presently it occurred to him that he wished he was
+sick; then he could stay home from school. Here was a vague
+possibility. He canvassed his system. No ailment was found, and he
+investigated again. This time he thought he could detect colicky
+symptoms, and he began to encourage them with considerable hope. But
+they soon grew feeble, and presently died wholly away. He reflected
+further. Suddenly he discovered something. One of his upper front teeth
+was loose. This was lucky; he was about to begin to groan, as a
+"starter," as he called it, when it occurred to him that if he came
+into court with that argument, his aunt would pull it out, and that
+would hurt. So he thought he would hold the tooth in reserve for the
+present, and seek further. Nothing offered for some little time, and
+then he remembered hearing the doctor tell about a certain thing that
+laid up a patient for two or three weeks and threatened to make him
+lose a finger. So the boy eagerly drew his sore toe from under the
+sheet and held it up for inspection. But now he did not know the
+necessary symptoms. However, it seemed well worth while to chance it,
+so he fell to groaning with considerable spirit.
+
+But Sid slept on unconscious.
+
+Tom groaned louder, and fancied that he began to feel pain in the toe.
+
+No result from Sid.
+
+Tom was panting with his exertions by this time. He took a rest and
+then swelled himself up and fetched a succession of admirable groans.
+
+Sid snored on.
+
+Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
+worked well, and Tom began to groan again. Sid yawned, stretched, then
+brought himself up on his elbow with a snort, and began to stare at
+Tom. Tom went on groaning. Sid said:
+
+"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
+Tom?" And he shook him and looked in his face anxiously.
+
+Tom moaned out:
+
+"Oh, don't, Sid. Don't joggle me."
+
+"Why, what's the matter, Tom? I must call auntie."
+
+"No--never mind. It'll be over by and by, maybe. Don't call anybody."
+
+"But I must! DON'T groan so, Tom, it's awful. How long you been this
+way?"
+
+"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
+
+"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
+flesh crawl to hear you. Tom, what is the matter?"
+
+"I forgive you everything, Sid. [Groan.] Everything you've ever done
+to me. When I'm gone--"
+
+"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
+
+"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
+give my window-sash and my cat with one eye to that new girl that's
+come to town, and tell her--"
+
+But Sid had snatched his clothes and gone. Tom was suffering in
+reality, now, so handsomely was his imagination working, and so his
+groans had gathered quite a genuine tone.
+
+Sid flew down-stairs and said:
+
+"Oh, Aunt Polly, come! Tom's dying!"
+
+"Dying!"
+
+"Yes'm. Don't wait--come quick!"
+
+"Rubbage! I don't believe it!"
+
+But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
+And her face grew white, too, and her lip trembled. When she reached
+the bedside she gasped out:
+
+"You, Tom! Tom, what's the matter with you?"
+
+"Oh, auntie, I'm--"
+
+"What's the matter with you--what is the matter with you, child?"
+
+"Oh, auntie, my sore toe's mortified!"
+
+The old lady sank down into a chair and laughed a little, then cried a
+little, then did both together. This restored her and she said:
+
+"Tom, what a turn you did give me. Now you shut up that nonsense and
+climb out of this."
+
+The groans ceased and the pain vanished from the toe. The boy felt a
+little foolish, and he said:
+
+"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
+tooth at all."
+
+"Your tooth, indeed! What's the matter with your tooth?"
+
+"One of them's loose, and it aches perfectly awful."
+
+"There, there, now, don't begin that groaning again. Open your mouth.
+Well--your tooth IS loose, but you're not going to die about that.
+Mary, get me a silk thread, and a chunk of fire out of the kitchen."
+
+Tom said:
+
+"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
+I may never stir if it does. Please don't, auntie. I don't want to stay
+home from school."
+
+"Oh, you don't, don't you? So all this row was because you thought
+you'd get to stay home from school and go a-fishing? Tom, Tom, I love
+you so, and you seem to try every way you can to break my old heart
+with your outrageousness." By this time the dental instruments were
+ready. The old lady made one end of the silk thread fast to Tom's tooth
+with a loop and tied the other to the bedpost. Then she seized the
+chunk of fire and suddenly thrust it almost into the boy's face. The
+tooth hung dangling by the bedpost, now.
+
+But all trials bring their compensations. As Tom wended to school
+after breakfast, he was the envy of every boy he met because the gap in
+his upper row of teeth enabled him to expectorate in a new and
+admirable way. He gathered quite a following of lads interested in the
+exhibition; and one that had cut his finger and had been a centre of
+fascination and homage up to this time, now found himself suddenly
+without an adherent, and shorn of his glory. His heart was heavy, and
+he said with a disdain which he did not feel that it wasn't anything to
+spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
+wandered away a dismantled hero.
+
+Shortly Tom came upon the juvenile pariah of the village, Huckleberry
+Finn, son of the town drunkard. Huckleberry was cordially hated and
+dreaded by all the mothers of the town, because he was idle and lawless
+and vulgar and bad--and because all their children admired him so, and
+delighted in his forbidden society, and wished they dared to be like
+him. Tom was like the rest of the respectable boys, in that he envied
+Huckleberry his gaudy outcast condition, and was under strict orders
+not to play with him. So he played with him every time he got a chance.
+Huckleberry was always dressed in the cast-off clothes of full-grown
+men, and they were in perennial bloom and fluttering with rags. His hat
+was a vast ruin with a wide crescent lopped out of its brim; his coat,
+when he wore one, hung nearly to his heels and had the rearward buttons
+far down the back; but one suspender supported his trousers; the seat
+of the trousers bagged low and contained nothing, the fringed legs
+dragged in the dirt when not rolled up.
+
+Huckleberry came and went, at his own free will. He slept on doorsteps
+in fine weather and in empty hogsheads in wet; he did not have to go to
+school or to church, or call any being master or obey anybody; he could
+go fishing or swimming when and where he chose, and stay as long as it
+suited him; nobody forbade him to fight; he could sit up as late as he
+pleased; he was always the first boy that went barefoot in the spring
+and the last to resume leather in the fall; he never had to wash, nor
+put on clean clothes; he could swear wonderfully. In a word, everything
+that goes to make life precious that boy had. So thought every
+harassed, hampered, respectable boy in St. Petersburg.
+
+Tom hailed the romantic outcast:
+
+"Hello, Huckleberry!"
+
+"Hello yourself, and see how you like it."
+
+"What's that you got?"
+
+"Dead cat."
+
+"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
+
+"Bought him off'n a boy."
+
+"What did you give?"
+
+"I give a blue ticket and a bladder that I got at the slaughter-house."
+
+"Where'd you get the blue ticket?"
+
+"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
+
+"Say--what is dead cats good for, Huck?"
+
+"Good for? Cure warts with."
+
+"No! Is that so? I know something that's better."
+
+"I bet you don't. What is it?"
+
+"Why, spunk-water."
+
+"Spunk-water! I wouldn't give a dern for spunk-water."
+
+"You wouldn't, wouldn't you? D'you ever try it?"
+
+"No, I hain't. But Bob Tanner did."
+
+"Who told you so!"
+
+"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
+told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
+the nigger told me. There now!"
+
+"Well, what of it? They'll all lie. Leastways all but the nigger. I
+don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
+you tell me how Bob Tanner done it, Huck."
+
+"Why, he took and dipped his hand in a rotten stump where the
+rain-water was."
+
+"In the daytime?"
+
+"Certainly."
+
+"With his face to the stump?"
+
+"Yes. Least I reckon so."
+
+"Did he say anything?"
+
+"I don't reckon he did. I don't know."
+
+"Aha! Talk about trying to cure warts with spunk-water such a blame
+fool way as that! Why, that ain't a-going to do any good. You got to go
+all by yourself, to the middle of the woods, where you know there's a
+spunk-water stump, and just as it's midnight you back up against the
+stump and jam your hand in and say:
+
+ 'Barley-corn, barley-corn, injun-meal shorts,
+ Spunk-water, spunk-water, swaller these warts,'
+
+and then walk away quick, eleven steps, with your eyes shut, and then
+turn around three times and walk home without speaking to anybody.
+Because if you speak the charm's busted."
+
+"Well, that sounds like a good way; but that ain't the way Bob Tanner
+done."
+
+"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
+town; and he wouldn't have a wart on him if he'd knowed how to work
+spunk-water. I've took off thousands of warts off of my hands that way,
+Huck. I play with frogs so much that I've always got considerable many
+warts. Sometimes I take 'em off with a bean."
+
+"Yes, bean's good. I've done that."
+
+"Have you? What's your way?"
+
+"You take and split the bean, and cut the wart so as to get some
+blood, and then you put the blood on one piece of the bean and take and
+dig a hole and bury it 'bout midnight at the crossroads in the dark of
+the moon, and then you burn up the rest of the bean. You see that piece
+that's got the blood on it will keep drawing and drawing, trying to
+fetch the other piece to it, and so that helps the blood to draw the
+wart, and pretty soon off she comes."
+
+"Yes, that's it, Huck--that's it; though when you're burying it if you
+say 'Down bean; off wart; come no more to bother me!' it's better.
+That's the way Joe Harper does, and he's been nearly to Coonville and
+most everywheres. But say--how do you cure 'em with dead cats?"
+
+"Why, you take your cat and go and get in the graveyard 'long about
+midnight when somebody that was wicked has been buried; and when it's
+midnight a devil will come, or maybe two or three, but you can't see
+'em, you can only hear something like the wind, or maybe hear 'em talk;
+and when they're taking that feller away, you heave your cat after 'em
+and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
+done with ye!' That'll fetch ANY wart."
+
+"Sounds right. D'you ever try it, Huck?"
+
+"No, but old Mother Hopkins told me."
+
+"Well, I reckon it's so, then. Becuz they say she's a witch."
+
+"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
+self. He come along one day, and he see she was a-witching him, so he
+took up a rock, and if she hadn't dodged, he'd a got her. Well, that
+very night he rolled off'n a shed wher' he was a layin drunk, and broke
+his arm."
+
+"Why, that's awful. How did he know she was a-witching him?"
+
+"Lord, pap can tell, easy. Pap says when they keep looking at you
+right stiddy, they're a-witching you. Specially if they mumble. Becuz
+when they mumble they're saying the Lord's Prayer backards."
+
+"Say, Hucky, when you going to try the cat?"
+
+"To-night. I reckon they'll come after old Hoss Williams to-night."
+
+"But they buried him Saturday. Didn't they get him Saturday night?"
+
+"Why, how you talk! How could their charms work till midnight?--and
+THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
+reckon."
+
+"I never thought of that. That's so. Lemme go with you?"
+
+"Of course--if you ain't afeard."
+
+"Afeard! 'Tain't likely. Will you meow?"
+
+"Yes--and you meow back, if you get a chance. Last time, you kep' me
+a-meowing around till old Hays went to throwing rocks at me and says
+'Dern that cat!' and so I hove a brick through his window--but don't
+you tell."
+
+"I won't. I couldn't meow that night, becuz auntie was watching me,
+but I'll meow this time. Say--what's that?"
+
+"Nothing but a tick."
+
+"Where'd you get him?"
+
+"Out in the woods."
+
+"What'll you take for him?"
+
+"I don't know. I don't want to sell him."
+
+"All right. It's a mighty small tick, anyway."
+
+"Oh, anybody can run a tick down that don't belong to them. I'm
+satisfied with it. It's a good enough tick for me."
+
+"Sho, there's ticks a plenty. I could have a thousand of 'em if I
+wanted to."
+
+"Well, why don't you? Becuz you know mighty well you can't. This is a
+pretty early tick, I reckon. It's the first one I've seen this year."
+
+"Say, Huck--I'll give you my tooth for him."
+
+"Less see it."
+
+Tom got out a bit of paper and carefully unrolled it. Huckleberry
+viewed it wistfully. The temptation was very strong. At last he said:
+
+"Is it genuwyne?"
+
+Tom lifted his lip and showed the vacancy.
+
+"Well, all right," said Huckleberry, "it's a trade."
+
+Tom enclosed the tick in the percussion-cap box that had lately been
+the pinchbug's prison, and the boys separated, each feeling wealthier
+than before.
+
+When Tom reached the little isolated frame schoolhouse, he strode in
+briskly, with the manner of one who had come with all honest speed.
+He hung his hat on a peg and flung himself into his seat with
+business-like alacrity. The master, throned on high in his great
+splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
+The interruption roused him.
+
+"Thomas Sawyer!"
+
+Tom knew that when his name was pronounced in full, it meant trouble.
+
+"Sir!"
+
+"Come up here. Now, sir, why are you late again, as usual?"
+
+Tom was about to take refuge in a lie, when he saw two long tails of
+yellow hair hanging down a back that he recognized by the electric
+sympathy of love; and by that form was THE ONLY VACANT PLACE on the
+girls' side of the schoolhouse. He instantly said:
+
+"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
+
+The master's pulse stood still, and he stared helplessly. The buzz of
+study ceased. The pupils wondered if this foolhardy boy had lost his
+mind. The master said:
+
+"You--you did what?"
+
+"Stopped to talk with Huckleberry Finn."
+
+There was no mistaking the words.
+
+"Thomas Sawyer, this is the most astounding confession I have ever
+listened to. No mere ferule will answer for this offence. Take off your
+jacket."
+
+The master's arm performed until it was tired and the stock of
+switches notably diminished. Then the order followed:
+
+"Now, sir, go and sit with the girls! And let this be a warning to you."
+
+The titter that rippled around the room appeared to abash the boy, but
+in reality that result was caused rather more by his worshipful awe of
+his unknown idol and the dread pleasure that lay in his high good
+fortune. He sat down upon the end of the pine bench and the girl
+hitched herself away from him with a toss of her head. Nudges and winks
+and whispers traversed the room, but Tom sat still, with his arms upon
+the long, low desk before him, and seemed to study his book.
+
+By and by attention ceased from him, and the accustomed school murmur
+rose upon the dull air once more. Presently the boy began to steal
+furtive glances at the girl. She observed it, "made a mouth" at him and
+gave him the back of her head for the space of a minute. When she
+cautiously faced around again, a peach lay before her. She thrust it
+away. Tom gently put it back. She thrust it away again, but with less
+animosity. Tom patiently returned it to its place. Then she let it
+remain. Tom scrawled on his slate, "Please take it--I got more." The
+girl glanced at the words, but made no sign. Now the boy began to draw
+something on the slate, hiding his work with his left hand. For a time
+the girl refused to notice; but her human curiosity presently began to
+manifest itself by hardly perceptible signs. The boy worked on,
+apparently unconscious. The girl made a sort of noncommittal attempt to
+see, but the boy did not betray that he was aware of it. At last she
+gave in and hesitatingly whispered:
+
+"Let me see it."
+
+Tom partly uncovered a dismal caricature of a house with two gable
+ends to it and a corkscrew of smoke issuing from the chimney. Then the
+girl's interest began to fasten itself upon the work and she forgot
+everything else. When it was finished, she gazed a moment, then
+whispered:
+
+"It's nice--make a man."
+
+The artist erected a man in the front yard, that resembled a derrick.
+He could have stepped over the house; but the girl was not
+hypercritical; she was satisfied with the monster, and whispered:
+
+"It's a beautiful man--now make me coming along."
+
+Tom drew an hour-glass with a full moon and straw limbs to it and
+armed the spreading fingers with a portentous fan. The girl said:
+
+"It's ever so nice--I wish I could draw."
+
+"It's easy," whispered Tom, "I'll learn you."
+
+"Oh, will you? When?"
+
+"At noon. Do you go home to dinner?"
+
+"I'll stay if you will."
+
+"Good--that's a whack. What's your name?"
+
+"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
+
+"That's the name they lick me by. I'm Tom when I'm good. You call me
+Tom, will you?"
+
+"Yes."
+
+Now Tom began to scrawl something on the slate, hiding the words from
+the girl. But she was not backward this time. She begged to see. Tom
+said:
+
+"Oh, it ain't anything."
+
+"Yes it is."
+
+"No it ain't. You don't want to see."
+
+"Yes I do, indeed I do. Please let me."
+
+"You'll tell."
+
+"No I won't--deed and deed and double deed won't."
+
+"You won't tell anybody at all? Ever, as long as you live?"
+
+"No, I won't ever tell ANYbody. Now let me."
+
+"Oh, YOU don't want to see!"
+
+"Now that you treat me so, I WILL see." And she put her small hand
+upon his and a little scuffle ensued, Tom pretending to resist in
+earnest but letting his hand slip by degrees till these words were
+revealed: "I LOVE YOU."
+
+"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
+and looked pleased, nevertheless.
+
+Just at this juncture the boy felt a slow, fateful grip closing on his
+ear, and a steady lifting impulse. In that wise he was borne across the
+house and deposited in his own seat, under a peppering fire of giggles
+from the whole school. Then the master stood over him during a few
+awful moments, and finally moved away to his throne without saying a
+word. But although Tom's ear tingled, his heart was jubilant.
+
+As the school quieted down Tom made an honest effort to study, but the
+turmoil within him was too great. In turn he took his place in the
+reading class and made a botch of it; then in the geography class and
+turned lakes into mountains, mountains into rivers, and rivers into
+continents, till chaos was come again; then in the spelling class, and
+got "turned down," by a succession of mere baby words, till he brought
+up at the foot and yielded up the pewter medal which he had worn with
+ostentation for months.
+
+
+
+CHAPTER VII
+
+THE harder Tom tried to fasten his mind on his book, the more his
+ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
+seemed to him that the noon recess would never come. The air was
+utterly dead. There was not a breath stirring. It was the sleepiest of
+sleepy days. The drowsing murmur of the five and twenty studying
+scholars soothed the soul like the spell that is in the murmur of bees.
+Away off in the flaming sunshine, Cardiff Hill lifted its soft green
+sides through a shimmering veil of heat, tinted with the purple of
+distance; a few birds floated on lazy wing high in the air; no other
+living thing was visible but some cows, and they were asleep. Tom's
+heart ached to be free, or else to have something of interest to do to
+pass the dreary time. His hand wandered into his pocket and his face
+lit up with a glow of gratitude that was prayer, though he did not know
+it. Then furtively the percussion-cap box came out. He released the
+tick and put him on the long flat desk. The creature probably glowed
+with a gratitude that amounted to prayer, too, at this moment, but it
+was premature: for when he started thankfully to travel off, Tom turned
+him aside with a pin and made him take a new direction.
+
+Tom's bosom friend sat next him, suffering just as Tom had been, and
+now he was deeply and gratefully interested in this entertainment in an
+instant. This bosom friend was Joe Harper. The two boys were sworn
+friends all the week, and embattled enemies on Saturdays. Joe took a
+pin out of his lapel and began to assist in exercising the prisoner.
+The sport grew in interest momently. Soon Tom said that they were
+interfering with each other, and neither getting the fullest benefit of
+the tick. So he put Joe's slate on the desk and drew a line down the
+middle of it from top to bottom.
+
+"Now," said he, "as long as he is on your side you can stir him up and
+I'll let him alone; but if you let him get away and get on my side,
+you're to leave him alone as long as I can keep him from crossing over."
+
+"All right, go ahead; start him up."
+
+The tick escaped from Tom, presently, and crossed the equator. Joe
+harassed him awhile, and then he got away and crossed back again. This
+change of base occurred often. While one boy was worrying the tick with
+absorbing interest, the other would look on with interest as strong,
+the two heads bowed together over the slate, and the two souls dead to
+all things else. At last luck seemed to settle and abide with Joe. The
+tick tried this, that, and the other course, and got as excited and as
+anxious as the boys themselves, but time and again just as he would
+have victory in his very grasp, so to speak, and Tom's fingers would be
+twitching to begin, Joe's pin would deftly head him off, and keep
+possession. At last Tom could stand it no longer. The temptation was
+too strong. So he reached out and lent a hand with his pin. Joe was
+angry in a moment. Said he:
+
+"Tom, you let him alone."
+
+"I only just want to stir him up a little, Joe."
+
+"No, sir, it ain't fair; you just let him alone."
+
+"Blame it, I ain't going to stir him much."
+
+"Let him alone, I tell you."
+
+"I won't!"
+
+"You shall--he's on my side of the line."
+
+"Look here, Joe Harper, whose is that tick?"
+
+"I don't care whose tick he is--he's on my side of the line, and you
+sha'n't touch him."
+
+"Well, I'll just bet I will, though. He's my tick and I'll do what I
+blame please with him, or die!"
+
+A tremendous whack came down on Tom's shoulders, and its duplicate on
+Joe's; and for the space of two minutes the dust continued to fly from
+the two jackets and the whole school to enjoy it. The boys had been too
+absorbed to notice the hush that had stolen upon the school awhile
+before when the master came tiptoeing down the room and stood over
+them. He had contemplated a good part of the performance before he
+contributed his bit of variety to it.
+
+When school broke up at noon, Tom flew to Becky Thatcher, and
+whispered in her ear:
+
+"Put on your bonnet and let on you're going home; and when you get to
+the corner, give the rest of 'em the slip, and turn down through the
+lane and come back. I'll go the other way and come it over 'em the same
+way."
+
+So the one went off with one group of scholars, and the other with
+another. In a little while the two met at the bottom of the lane, and
+when they reached the school they had it all to themselves. Then they
+sat together, with a slate before them, and Tom gave Becky the pencil
+and held her hand in his, guiding it, and so created another surprising
+house. When the interest in art began to wane, the two fell to talking.
+Tom was swimming in bliss. He said:
+
+"Do you love rats?"
+
+"No! I hate them!"
+
+"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
+head with a string."
+
+"No, I don't care for rats much, anyway. What I like is chewing-gum."
+
+"Oh, I should say so! I wish I had some now."
+
+"Do you? I've got some. I'll let you chew it awhile, but you must give
+it back to me."
+
+That was agreeable, so they chewed it turn about, and dangled their
+legs against the bench in excess of contentment.
+
+"Was you ever at a circus?" said Tom.
+
+"Yes, and my pa's going to take me again some time, if I'm good."
+
+"I been to the circus three or four times--lots of times. Church ain't
+shucks to a circus. There's things going on at a circus all the time.
+I'm going to be a clown in a circus when I grow up."
+
+"Oh, are you! That will be nice. They're so lovely, all spotted up."
+
+"Yes, that's so. And they get slathers of money--most a dollar a day,
+Ben Rogers says. Say, Becky, was you ever engaged?"
+
+"What's that?"
+
+"Why, engaged to be married."
+
+"No."
+
+"Would you like to?"
+
+"I reckon so. I don't know. What is it like?"
+
+"Like? Why it ain't like anything. You only just tell a boy you won't
+ever have anybody but him, ever ever ever, and then you kiss and that's
+all. Anybody can do it."
+
+"Kiss? What do you kiss for?"
+
+"Why, that, you know, is to--well, they always do that."
+
+"Everybody?"
+
+"Why, yes, everybody that's in love with each other. Do you remember
+what I wrote on the slate?"
+
+"Ye--yes."
+
+"What was it?"
+
+"I sha'n't tell you."
+
+"Shall I tell YOU?"
+
+"Ye--yes--but some other time."
+
+"No, now."
+
+"No, not now--to-morrow."
+
+"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
+easy."
+
+Becky hesitating, Tom took silence for consent, and passed his arm
+about her waist and whispered the tale ever so softly, with his mouth
+close to her ear. And then he added:
+
+"Now you whisper it to me--just the same."
+
+She resisted, for a while, and then said:
+
+"You turn your face away so you can't see, and then I will. But you
+mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
+
+"No, indeed, indeed I won't. Now, Becky."
+
+He turned his face away. She bent timidly around till her breath
+stirred his curls and whispered, "I--love--you!"
+
+Then she sprang away and ran around and around the desks and benches,
+with Tom after her, and took refuge in a corner at last, with her
+little white apron to her face. Tom clasped her about her neck and
+pleaded:
+
+"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
+of that--it ain't anything at all. Please, Becky." And he tugged at her
+apron and the hands.
+
+By and by she gave up, and let her hands drop; her face, all glowing
+with the struggle, came up and submitted. Tom kissed the red lips and
+said:
+
+"Now it's all done, Becky. And always after this, you know, you ain't
+ever to love anybody but me, and you ain't ever to marry anybody but
+me, ever never and forever. Will you?"
+
+"No, I'll never love anybody but you, Tom, and I'll never marry
+anybody but you--and you ain't to ever marry anybody but me, either."
+
+"Certainly. Of course. That's PART of it. And always coming to school
+or when we're going home, you're to walk with me, when there ain't
+anybody looking--and you choose me and I choose you at parties, because
+that's the way you do when you're engaged."
+
+"It's so nice. I never heard of it before."
+
+"Oh, it's ever so gay! Why, me and Amy Lawrence--"
+
+The big eyes told Tom his blunder and he stopped, confused.
+
+"Oh, Tom! Then I ain't the first you've ever been engaged to!"
+
+The child began to cry. Tom said:
+
+"Oh, don't cry, Becky, I don't care for her any more."
+
+"Yes, you do, Tom--you know you do."
+
+Tom tried to put his arm about her neck, but she pushed him away and
+turned her face to the wall, and went on crying. Tom tried again, with
+soothing words in his mouth, and was repulsed again. Then his pride was
+up, and he strode away and went outside. He stood about, restless and
+uneasy, for a while, glancing at the door, every now and then, hoping
+she would repent and come to find him. But she did not. Then he began
+to feel badly and fear that he was in the wrong. It was a hard struggle
+with him to make new advances, now, but he nerved himself to it and
+entered. She was still standing back there in the corner, sobbing, with
+her face to the wall. Tom's heart smote him. He went to her and stood a
+moment, not knowing exactly how to proceed. Then he said hesitatingly:
+
+"Becky, I--I don't care for anybody but you."
+
+No reply--but sobs.
+
+"Becky"--pleadingly. "Becky, won't you say something?"
+
+More sobs.
+
+Tom got out his chiefest jewel, a brass knob from the top of an
+andiron, and passed it around her so that she could see it, and said:
+
+"Please, Becky, won't you take it?"
+
+She struck it to the floor. Then Tom marched out of the house and over
+the hills and far away, to return to school no more that day. Presently
+Becky began to suspect. She ran to the door; he was not in sight; she
+flew around to the play-yard; he was not there. Then she called:
+
+"Tom! Come back, Tom!"
+
+She listened intently, but there was no answer. She had no companions
+but silence and loneliness. So she sat down to cry again and upbraid
+herself; and by this time the scholars began to gather again, and she
+had to hide her griefs and still her broken heart and take up the cross
+of a long, dreary, aching afternoon, with none among the strangers
+about her to exchange sorrows with.
+
+
+
+CHAPTER VIII
+
+TOM dodged hither and thither through lanes until he was well out of
+the track of returning scholars, and then fell into a moody jog. He
+crossed a small "branch" two or three times, because of a prevailing
+juvenile superstition that to cross water baffled pursuit. Half an hour
+later he was disappearing behind the Douglas mansion on the summit of
+Cardiff Hill, and the schoolhouse was hardly distinguishable away off
+in the valley behind him. He entered a dense wood, picked his pathless
+way to the centre of it, and sat down on a mossy spot under a spreading
+oak. There was not even a zephyr stirring; the dead noonday heat had
+even stilled the songs of the birds; nature lay in a trance that was
+broken by no sound but the occasional far-off hammering of a
+woodpecker, and this seemed to render the pervading silence and sense
+of loneliness the more profound. The boy's soul was steeped in
+melancholy; his feelings were in happy accord with his surroundings. He
+sat long with his elbows on his knees and his chin in his hands,
+meditating. It seemed to him that life was but a trouble, at best, and
+he more than half envied Jimmy Hodges, so lately released; it must be
+very peaceful, he thought, to lie and slumber and dream forever and
+ever, with the wind whispering through the trees and caressing the
+grass and the flowers over the grave, and nothing to bother and grieve
+about, ever any more. If he only had a clean Sunday-school record he
+could be willing to go, and be done with it all. Now as to this girl.
+What had he done? Nothing. He had meant the best in the world, and been
+treated like a dog--like a very dog. She would be sorry some day--maybe
+when it was too late. Ah, if he could only die TEMPORARILY!
+
+But the elastic heart of youth cannot be compressed into one
+constrained shape long at a time. Tom presently began to drift
+insensibly back into the concerns of this life again. What if he turned
+his back, now, and disappeared mysteriously? What if he went away--ever
+so far away, into unknown countries beyond the seas--and never came
+back any more! How would she feel then! The idea of being a clown
+recurred to him now, only to fill him with disgust. For frivolity and
+jokes and spotted tights were an offense, when they intruded themselves
+upon a spirit that was exalted into the vague august realm of the
+romantic. No, he would be a soldier, and return after long years, all
+war-worn and illustrious. No--better still, he would join the Indians,
+and hunt buffaloes and go on the warpath in the mountain ranges and the
+trackless great plains of the Far West, and away in the future come
+back a great chief, bristling with feathers, hideous with paint, and
+prance into Sunday-school, some drowsy summer morning, with a
+bloodcurdling war-whoop, and sear the eyeballs of all his companions
+with unappeasable envy. But no, there was something gaudier even than
+this. He would be a pirate! That was it! NOW his future lay plain
+before him, and glowing with unimaginable splendor. How his name would
+fill the world, and make people shudder! How gloriously he would go
+plowing the dancing seas, in his long, low, black-hulled racer, the
+Spirit of the Storm, with his grisly flag flying at the fore! And at
+the zenith of his fame, how he would suddenly appear at the old village
+and stalk into church, brown and weather-beaten, in his black velvet
+doublet and trunks, his great jack-boots, his crimson sash, his belt
+bristling with horse-pistols, his crime-rusted cutlass at his side, his
+slouch hat with waving plumes, his black flag unfurled, with the skull
+and crossbones on it, and hear with swelling ecstasy the whisperings,
+"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
+
+Yes, it was settled; his career was determined. He would run away from
+home and enter upon it. He would start the very next morning. Therefore
+he must now begin to get ready. He would collect his resources
+together. He went to a rotten log near at hand and began to dig under
+one end of it with his Barlow knife. He soon struck wood that sounded
+hollow. He put his hand there and uttered this incantation impressively:
+
+"What hasn't come here, come! What's here, stay here!"
+
+Then he scraped away the dirt, and exposed a pine shingle. He took it
+up and disclosed a shapely little treasure-house whose bottom and sides
+were of shingles. In it lay a marble. Tom's astonishment was boundless!
+He scratched his head with a perplexed air, and said:
+
+"Well, that beats anything!"
+
+Then he tossed the marble away pettishly, and stood cogitating. The
+truth was, that a superstition of his had failed, here, which he and
+all his comrades had always looked upon as infallible. If you buried a
+marble with certain necessary incantations, and left it alone a
+fortnight, and then opened the place with the incantation he had just
+used, you would find that all the marbles you had ever lost had
+gathered themselves together there, meantime, no matter how widely they
+had been separated. But now, this thing had actually and unquestionably
+failed. Tom's whole structure of faith was shaken to its foundations.
+He had many a time heard of this thing succeeding but never of its
+failing before. It did not occur to him that he had tried it several
+times before, himself, but could never find the hiding-places
+afterward. He puzzled over the matter some time, and finally decided
+that some witch had interfered and broken the charm. He thought he
+would satisfy himself on that point; so he searched around till he
+found a small sandy spot with a little funnel-shaped depression in it.
+He laid himself down and put his mouth close to this depression and
+called--
+
+"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
+doodle-bug, tell me what I want to know!"
+
+The sand began to work, and presently a small black bug appeared for a
+second and then darted under again in a fright.
+
+"He dasn't tell! So it WAS a witch that done it. I just knowed it."
+
+He well knew the futility of trying to contend against witches, so he
+gave up discouraged. But it occurred to him that he might as well have
+the marble he had just thrown away, and therefore he went and made a
+patient search for it. But he could not find it. Now he went back to
+his treasure-house and carefully placed himself just as he had been
+standing when he tossed the marble away; then he took another marble
+from his pocket and tossed it in the same way, saying:
+
+"Brother, go find your brother!"
+
+He watched where it stopped, and went there and looked. But it must
+have fallen short or gone too far; so he tried twice more. The last
+repetition was successful. The two marbles lay within a foot of each
+other.
+
+Just here the blast of a toy tin trumpet came faintly down the green
+aisles of the forest. Tom flung off his jacket and trousers, turned a
+suspender into a belt, raked away some brush behind the rotten log,
+disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
+a moment had seized these things and bounded away, barelegged, with
+fluttering shirt. He presently halted under a great elm, blew an
+answering blast, and then began to tiptoe and look warily out, this way
+and that. He said cautiously--to an imaginary company:
+
+"Hold, my merry men! Keep hid till I blow."
+
+Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
+Tom called:
+
+"Hold! Who comes here into Sherwood Forest without my pass?"
+
+"Guy of Guisborne wants no man's pass. Who art thou that--that--"
+
+"Dares to hold such language," said Tom, prompting--for they talked
+"by the book," from memory.
+
+"Who art thou that dares to hold such language?"
+
+"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
+
+"Then art thou indeed that famous outlaw? Right gladly will I dispute
+with thee the passes of the merry wood. Have at thee!"
+
+They took their lath swords, dumped their other traps on the ground,
+struck a fencing attitude, foot to foot, and began a grave, careful
+combat, "two up and two down." Presently Tom said:
+
+"Now, if you've got the hang, go it lively!"
+
+So they "went it lively," panting and perspiring with the work. By and
+by Tom shouted:
+
+"Fall! fall! Why don't you fall?"
+
+"I sha'n't! Why don't you fall yourself? You're getting the worst of
+it."
+
+"Why, that ain't anything. I can't fall; that ain't the way it is in
+the book. The book says, 'Then with one back-handed stroke he slew poor
+Guy of Guisborne.' You're to turn around and let me hit you in the
+back."
+
+There was no getting around the authorities, so Joe turned, received
+the whack and fell.
+
+"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
+
+"Why, I can't do that, it ain't in the book."
+
+"Well, it's blamed mean--that's all."
+
+"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
+lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
+you be Robin Hood a little while and kill me."
+
+This was satisfactory, and so these adventures were carried out. Then
+Tom became Robin Hood again, and was allowed by the treacherous nun to
+bleed his strength away through his neglected wound. And at last Joe,
+representing a whole tribe of weeping outlaws, dragged him sadly forth,
+gave his bow into his feeble hands, and Tom said, "Where this arrow
+falls, there bury poor Robin Hood under the greenwood tree." Then he
+shot the arrow and fell back and would have died, but he lit on a
+nettle and sprang up too gaily for a corpse.
+
+The boys dressed themselves, hid their accoutrements, and went off
+grieving that there were no outlaws any more, and wondering what modern
+civilization could claim to have done to compensate for their loss.
+They said they would rather be outlaws a year in Sherwood Forest than
+President of the United States forever.
+
+
+
+CHAPTER IX
+
+AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
+They said their prayers, and Sid was soon asleep. Tom lay awake and
+waited, in restless impatience. When it seemed to him that it must be
+nearly daylight, he heard the clock strike ten! This was despair. He
+would have tossed and fidgeted, as his nerves demanded, but he was
+afraid he might wake Sid. So he lay still, and stared up into the dark.
+Everything was dismally still. By and by, out of the stillness, little,
+scarcely perceptible noises began to emphasize themselves. The ticking
+of the clock began to bring itself into notice. Old beams began to
+crack mysteriously. The stairs creaked faintly. Evidently spirits were
+abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
+now the tiresome chirping of a cricket that no human ingenuity could
+locate, began. Next the ghastly ticking of a deathwatch in the wall at
+the bed's head made Tom shudder--it meant that somebody's days were
+numbered. Then the howl of a far-off dog rose on the night air, and was
+answered by a fainter howl from a remoter distance. Tom was in an
+agony. At last he was satisfied that time had ceased and eternity
+begun; he began to doze, in spite of himself; the clock chimed eleven,
+but he did not hear it. And then there came, mingling with his
+half-formed dreams, a most melancholy caterwauling. The raising of a
+neighboring window disturbed him. A cry of "Scat! you devil!" and the
+crash of an empty bottle against the back of his aunt's woodshed
+brought him wide awake, and a single minute later he was dressed and
+out of the window and creeping along the roof of the "ell" on all
+fours. He "meow'd" with caution once or twice, as he went; then jumped
+to the roof of the woodshed and thence to the ground. Huckleberry Finn
+was there, with his dead cat. The boys moved off and disappeared in the
+gloom. At the end of half an hour they were wading through the tall
+grass of the graveyard.
+
+It was a graveyard of the old-fashioned Western kind. It was on a
+hill, about a mile and a half from the village. It had a crazy board
+fence around it, which leaned inward in places, and outward the rest of
+the time, but stood upright nowhere. Grass and weeds grew rank over the
+whole cemetery. All the old graves were sunken in, there was not a
+tombstone on the place; round-topped, worm-eaten boards staggered over
+the graves, leaning for support and finding none. "Sacred to the memory
+of" So-and-So had been painted on them once, but it could no longer
+have been read, on the most of them, now, even if there had been light.
+
+A faint wind moaned through the trees, and Tom feared it might be the
+spirits of the dead, complaining at being disturbed. The boys talked
+little, and only under their breath, for the time and the place and the
+pervading solemnity and silence oppressed their spirits. They found the
+sharp new heap they were seeking, and ensconced themselves within the
+protection of three great elms that grew in a bunch within a few feet
+of the grave.
+
+Then they waited in silence for what seemed a long time. The hooting
+of a distant owl was all the sound that troubled the dead stillness.
+Tom's reflections grew oppressive. He must force some talk. So he said
+in a whisper:
+
+"Hucky, do you believe the dead people like it for us to be here?"
+
+Huckleberry whispered:
+
+"I wisht I knowed. It's awful solemn like, AIN'T it?"
+
+"I bet it is."
+
+There was a considerable pause, while the boys canvassed this matter
+inwardly. Then Tom whispered:
+
+"Say, Hucky--do you reckon Hoss Williams hears us talking?"
+
+"O' course he does. Least his sperrit does."
+
+Tom, after a pause:
+
+"I wish I'd said Mister Williams. But I never meant any harm.
+Everybody calls him Hoss."
+
+"A body can't be too partic'lar how they talk 'bout these-yer dead
+people, Tom."
+
+This was a damper, and conversation died again.
+
+Presently Tom seized his comrade's arm and said:
+
+"Sh!"
+
+"What is it, Tom?" And the two clung together with beating hearts.
+
+"Sh! There 'tis again! Didn't you hear it?"
+
+"I--"
+
+"There! Now you hear it."
+
+"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
+
+"I dono. Think they'll see us?"
+
+"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
+come."
+
+"Oh, don't be afeard. I don't believe they'll bother us. We ain't
+doing any harm. If we keep perfectly still, maybe they won't notice us
+at all."
+
+"I'll try to, Tom, but, Lord, I'm all of a shiver."
+
+"Listen!"
+
+The boys bent their heads together and scarcely breathed. A muffled
+sound of voices floated up from the far end of the graveyard.
+
+"Look! See there!" whispered Tom. "What is it?"
+
+"It's devil-fire. Oh, Tom, this is awful."
+
+Some vague figures approached through the gloom, swinging an
+old-fashioned tin lantern that freckled the ground with innumerable
+little spangles of light. Presently Huckleberry whispered with a
+shudder:
+
+"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
+Can you pray?"
+
+"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
+I lay me down to sleep, I--'"
+
+"Sh!"
+
+"What is it, Huck?"
+
+"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
+voice."
+
+"No--'tain't so, is it?"
+
+"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
+notice us. Drunk, the same as usual, likely--blamed old rip!"
+
+"All right, I'll keep still. Now they're stuck. Can't find it. Here
+they come again. Now they're hot. Cold again. Hot again. Red hot!
+They're p'inted right, this time. Say, Huck, I know another o' them
+voices; it's Injun Joe."
+
+"That's so--that murderin' half-breed! I'd druther they was devils a
+dern sight. What kin they be up to?"
+
+The whisper died wholly out, now, for the three men had reached the
+grave and stood within a few feet of the boys' hiding-place.
+
+"Here it is," said the third voice; and the owner of it held the
+lantern up and revealed the face of young Doctor Robinson.
+
+Potter and Injun Joe were carrying a handbarrow with a rope and a
+couple of shovels on it. They cast down their load and began to open
+the grave. The doctor put the lantern at the head of the grave and came
+and sat down with his back against one of the elm trees. He was so
+close the boys could have touched him.
+
+"Hurry, men!" he said, in a low voice; "the moon might come out at any
+moment."
+
+They growled a response and went on digging. For some time there was
+no noise but the grating sound of the spades discharging their freight
+of mould and gravel. It was very monotonous. Finally a spade struck
+upon the coffin with a dull woody accent, and within another minute or
+two the men had hoisted it out on the ground. They pried off the lid
+with their shovels, got out the body and dumped it rudely on the
+ground. The moon drifted from behind the clouds and exposed the pallid
+face. The barrow was got ready and the corpse placed on it, covered
+with a blanket, and bound to its place with the rope. Potter took out a
+large spring-knife and cut off the dangling end of the rope and then
+said:
+
+"Now the cussed thing's ready, Sawbones, and you'll just out with
+another five, or here she stays."
+
+"That's the talk!" said Injun Joe.
+
+"Look here, what does this mean?" said the doctor. "You required your
+pay in advance, and I've paid you."
+
+"Yes, and you done more than that," said Injun Joe, approaching the
+doctor, who was now standing. "Five years ago you drove me away from
+your father's kitchen one night, when I come to ask for something to
+eat, and you said I warn't there for any good; and when I swore I'd get
+even with you if it took a hundred years, your father had me jailed for
+a vagrant. Did you think I'd forget? The Injun blood ain't in me for
+nothing. And now I've GOT you, and you got to SETTLE, you know!"
+
+He was threatening the doctor, with his fist in his face, by this
+time. The doctor struck out suddenly and stretched the ruffian on the
+ground. Potter dropped his knife, and exclaimed:
+
+"Here, now, don't you hit my pard!" and the next moment he had
+grappled with the doctor and the two were struggling with might and
+main, trampling the grass and tearing the ground with their heels.
+Injun Joe sprang to his feet, his eyes flaming with passion, snatched
+up Potter's knife, and went creeping, catlike and stooping, round and
+round about the combatants, seeking an opportunity. All at once the
+doctor flung himself free, seized the heavy headboard of Williams'
+grave and felled Potter to the earth with it--and in the same instant
+the half-breed saw his chance and drove the knife to the hilt in the
+young man's breast. He reeled and fell partly upon Potter, flooding him
+with his blood, and in the same moment the clouds blotted out the
+dreadful spectacle and the two frightened boys went speeding away in
+the dark.
+
+Presently, when the moon emerged again, Injun Joe was standing over
+the two forms, contemplating them. The doctor murmured inarticulately,
+gave a long gasp or two and was still. The half-breed muttered:
+
+"THAT score is settled--damn you."
+
+Then he robbed the body. After which he put the fatal knife in
+Potter's open right hand, and sat down on the dismantled coffin. Three
+--four--five minutes passed, and then Potter began to stir and moan. His
+hand closed upon the knife; he raised it, glanced at it, and let it
+fall, with a shudder. Then he sat up, pushing the body from him, and
+gazed at it, and then around him, confusedly. His eyes met Joe's.
+
+"Lord, how is this, Joe?" he said.
+
+"It's a dirty business," said Joe, without moving.
+
+"What did you do it for?"
+
+"I! I never done it!"
+
+"Look here! That kind of talk won't wash."
+
+Potter trembled and grew white.
+
+"I thought I'd got sober. I'd no business to drink to-night. But it's
+in my head yet--worse'n when we started here. I'm all in a muddle;
+can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
+feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
+never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
+so young and promising."
+
+"Why, you two was scuffling, and he fetched you one with the headboard
+and you fell flat; and then up you come, all reeling and staggering
+like, and snatched the knife and jammed it into him, just as he fetched
+you another awful clip--and here you've laid, as dead as a wedge til
+now."
+
+"Oh, I didn't know what I was a-doing. I wish I may die this minute if
+I did. It was all on account of the whiskey and the excitement, I
+reckon. I never used a weepon in my life before, Joe. I've fought, but
+never with weepons. They'll all say that. Joe, don't tell! Say you
+won't tell, Joe--that's a good feller. I always liked you, Joe, and
+stood up for you, too. Don't you remember? You WON'T tell, WILL you,
+Joe?" And the poor creature dropped on his knees before the stolid
+murderer, and clasped his appealing hands.
+
+"No, you've always been fair and square with me, Muff Potter, and I
+won't go back on you. There, now, that's as fair as a man can say."
+
+"Oh, Joe, you're an angel. I'll bless you for this the longest day I
+live." And Potter began to cry.
+
+"Come, now, that's enough of that. This ain't any time for blubbering.
+You be off yonder way and I'll go this. Move, now, and don't leave any
+tracks behind you."
+
+Potter started on a trot that quickly increased to a run. The
+half-breed stood looking after him. He muttered:
+
+"If he's as much stunned with the lick and fuddled with the rum as he
+had the look of being, he won't think of the knife till he's gone so
+far he'll be afraid to come back after it to such a place by himself
+--chicken-heart!"
+
+Two or three minutes later the murdered man, the blanketed corpse, the
+lidless coffin, and the open grave were under no inspection but the
+moon's. The stillness was complete again, too.
+
+
+
+CHAPTER X
+
+THE two boys flew on and on, toward the village, speechless with
+horror. They glanced backward over their shoulders from time to time,
+apprehensively, as if they feared they might be followed. Every stump
+that started up in their path seemed a man and an enemy, and made them
+catch their breath; and as they sped by some outlying cottages that lay
+near the village, the barking of the aroused watch-dogs seemed to give
+wings to their feet.
+
+"If we can only get to the old tannery before we break down!"
+whispered Tom, in short catches between breaths. "I can't stand it much
+longer."
+
+Huckleberry's hard pantings were his only reply, and the boys fixed
+their eyes on the goal of their hopes and bent to their work to win it.
+They gained steadily on it, and at last, breast to breast, they burst
+through the open door and fell grateful and exhausted in the sheltering
+shadows beyond. By and by their pulses slowed down, and Tom whispered:
+
+"Huckleberry, what do you reckon'll come of this?"
+
+"If Doctor Robinson dies, I reckon hanging'll come of it."
+
+"Do you though?"
+
+"Why, I KNOW it, Tom."
+
+Tom thought a while, then he said:
+
+"Who'll tell? We?"
+
+"What are you talking about? S'pose something happened and Injun Joe
+DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
+we're a laying here."
+
+"That's just what I was thinking to myself, Huck."
+
+"If anybody tells, let Muff Potter do it, if he's fool enough. He's
+generally drunk enough."
+
+Tom said nothing--went on thinking. Presently he whispered:
+
+"Huck, Muff Potter don't know it. How can he tell?"
+
+"What's the reason he don't know it?"
+
+"Because he'd just got that whack when Injun Joe done it. D'you reckon
+he could see anything? D'you reckon he knowed anything?"
+
+"By hokey, that's so, Tom!"
+
+"And besides, look-a-here--maybe that whack done for HIM!"
+
+"No, 'taint likely, Tom. He had liquor in him; I could see that; and
+besides, he always has. Well, when pap's full, you might take and belt
+him over the head with a church and you couldn't phase him. He says so,
+his own self. So it's the same with Muff Potter, of course. But if a
+man was dead sober, I reckon maybe that whack might fetch him; I dono."
+
+After another reflective silence, Tom said:
+
+"Hucky, you sure you can keep mum?"
+
+"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
+make any more of drownding us than a couple of cats, if we was to
+squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
+take and swear to one another--that's what we got to do--swear to keep
+mum."
+
+"I'm agreed. It's the best thing. Would you just hold hands and swear
+that we--"
+
+"Oh no, that wouldn't do for this. That's good enough for little
+rubbishy common things--specially with gals, cuz THEY go back on you
+anyway, and blab if they get in a huff--but there orter be writing
+'bout a big thing like this. And blood."
+
+Tom's whole being applauded this idea. It was deep, and dark, and
+awful; the hour, the circumstances, the surroundings, were in keeping
+with it. He picked up a clean pine shingle that lay in the moonlight,
+took a little fragment of "red keel" out of his pocket, got the moon on
+his work, and painfully scrawled these lines, emphasizing each slow
+down-stroke by clamping his tongue between his teeth, and letting up
+the pressure on the up-strokes. [See next page.]
+
+ "Huck Finn and
+ Tom Sawyer swears
+ they will keep mum
+ about This and They
+ wish They may Drop
+ down dead in Their
+ Tracks if They ever
+ Tell and Rot."
+
+Huckleberry was filled with admiration of Tom's facility in writing,
+and the sublimity of his language. He at once took a pin from his lapel
+and was going to prick his flesh, but Tom said:
+
+"Hold on! Don't do that. A pin's brass. It might have verdigrease on
+it."
+
+"What's verdigrease?"
+
+"It's p'ison. That's what it is. You just swaller some of it once
+--you'll see."
+
+So Tom unwound the thread from one of his needles, and each boy
+pricked the ball of his thumb and squeezed out a drop of blood. In
+time, after many squeezes, Tom managed to sign his initials, using the
+ball of his little finger for a pen. Then he showed Huckleberry how to
+make an H and an F, and the oath was complete. They buried the shingle
+close to the wall, with some dismal ceremonies and incantations, and
+the fetters that bound their tongues were considered to be locked and
+the key thrown away.
+
+A figure crept stealthily through a break in the other end of the
+ruined building, now, but they did not notice it.
+
+"Tom," whispered Huckleberry, "does this keep us from EVER telling
+--ALWAYS?"
+
+"Of course it does. It don't make any difference WHAT happens, we got
+to keep mum. We'd drop down dead--don't YOU know that?"
+
+"Yes, I reckon that's so."
+
+They continued to whisper for some little time. Presently a dog set up
+a long, lugubrious howl just outside--within ten feet of them. The boys
+clasped each other suddenly, in an agony of fright.
+
+"Which of us does he mean?" gasped Huckleberry.
+
+"I dono--peep through the crack. Quick!"
+
+"No, YOU, Tom!"
+
+"I can't--I can't DO it, Huck!"
+
+"Please, Tom. There 'tis again!"
+
+"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
+Harbison." *
+
+[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
+him as "Harbison's Bull," but a son or a dog of that name was "Bull
+Harbison."]
+
+"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
+bet anything it was a STRAY dog."
+
+The dog howled again. The boys' hearts sank once more.
+
+"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
+
+Tom, quaking with fear, yielded, and put his eye to the crack. His
+whisper was hardly audible when he said:
+
+"Oh, Huck, IT S A STRAY DOG!"
+
+"Quick, Tom, quick! Who does he mean?"
+
+"Huck, he must mean us both--we're right together."
+
+"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
+where I'LL go to. I been so wicked."
+
+"Dad fetch it! This comes of playing hookey and doing everything a
+feller's told NOT to do. I might a been good, like Sid, if I'd a tried
+--but no, I wouldn't, of course. But if ever I get off this time, I lay
+I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
+
+"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
+Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
+lordy, I wisht I only had half your chance."
+
+Tom choked off and whispered:
+
+"Look, Hucky, look! He's got his BACK to us!"
+
+Hucky looked, with joy in his heart.
+
+"Well, he has, by jingoes! Did he before?"
+
+"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
+you know. NOW who can he mean?"
+
+The howling stopped. Tom pricked up his ears.
+
+"Sh! What's that?" he whispered.
+
+"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
+
+"That IS it! Where 'bouts is it, Huck?"
+
+"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
+sleep there, sometimes, 'long with the hogs, but laws bless you, he
+just lifts things when HE snores. Besides, I reckon he ain't ever
+coming back to this town any more."
+
+The spirit of adventure rose in the boys' souls once more.
+
+"Hucky, do you das't to go if I lead?"
+
+"I don't like to, much. Tom, s'pose it's Injun Joe!"
+
+Tom quailed. But presently the temptation rose up strong again and the
+boys agreed to try, with the understanding that they would take to
+their heels if the snoring stopped. So they went tiptoeing stealthily
+down, the one behind the other. When they had got to within five steps
+of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
+The man moaned, writhed a little, and his face came into the moonlight.
+It was Muff Potter. The boys' hearts had stood still, and their hopes
+too, when the man moved, but their fears passed away now. They tiptoed
+out, through the broken weather-boarding, and stopped at a little
+distance to exchange a parting word. That long, lugubrious howl rose on
+the night air again! They turned and saw the strange dog standing
+within a few feet of where Potter was lying, and FACING Potter, with
+his nose pointing heavenward.
+
+"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
+
+"Say, Tom--they say a stray dog come howling around Johnny Miller's
+house, 'bout midnight, as much as two weeks ago; and a whippoorwill
+come in and lit on the banisters and sung, the very same evening; and
+there ain't anybody dead there yet."
+
+"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
+in the kitchen fire and burn herself terrible the very next Saturday?"
+
+"Yes, but she ain't DEAD. And what's more, she's getting better, too."
+
+"All right, you wait and see. She's a goner, just as dead sure as Muff
+Potter's a goner. That's what the niggers say, and they know all about
+these kind of things, Huck."
+
+Then they separated, cogitating. When Tom crept in at his bedroom
+window the night was almost spent. He undressed with excessive caution,
+and fell asleep congratulating himself that nobody knew of his
+escapade. He was not aware that the gently-snoring Sid was awake, and
+had been so for an hour.
+
+When Tom awoke, Sid was dressed and gone. There was a late look in the
+light, a late sense in the atmosphere. He was startled. Why had he not
+been called--persecuted till he was up, as usual? The thought filled
+him with bodings. Within five minutes he was dressed and down-stairs,
+feeling sore and drowsy. The family were still at table, but they had
+finished breakfast. There was no voice of rebuke; but there were
+averted eyes; there was a silence and an air of solemnity that struck a
+chill to the culprit's heart. He sat down and tried to seem gay, but it
+was up-hill work; it roused no smile, no response, and he lapsed into
+silence and let his heart sink down to the depths.
+
+After breakfast his aunt took him aside, and Tom almost brightened in
+the hope that he was going to be flogged; but it was not so. His aunt
+wept over him and asked him how he could go and break her old heart so;
+and finally told him to go on, and ruin himself and bring her gray
+hairs with sorrow to the grave, for it was no use for her to try any
+more. This was worse than a thousand whippings, and Tom's heart was
+sorer now than his body. He cried, he pleaded for forgiveness, promised
+to reform over and over again, and then received his dismissal, feeling
+that he had won but an imperfect forgiveness and established but a
+feeble confidence.
+
+He left the presence too miserable to even feel revengeful toward Sid;
+and so the latter's prompt retreat through the back gate was
+unnecessary. He moped to school gloomy and sad, and took his flogging,
+along with Joe Harper, for playing hookey the day before, with the air
+of one whose heart was busy with heavier woes and wholly dead to
+trifles. Then he betook himself to his seat, rested his elbows on his
+desk and his jaws in his hands, and stared at the wall with the stony
+stare of suffering that has reached the limit and can no further go.
+His elbow was pressing against some hard substance. After a long time
+he slowly and sadly changed his position, and took up this object with
+a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
+sigh followed, and his heart broke. It was his brass andiron knob!
+
+This final feather broke the camel's back.
+
+
+
+CHAPTER XI
+
+CLOSE upon the hour of noon the whole village was suddenly electrified
+with the ghastly news. No need of the as yet undreamed-of telegraph;
+the tale flew from man to man, from group to group, from house to
+house, with little less than telegraphic speed. Of course the
+schoolmaster gave holiday for that afternoon; the town would have
+thought strangely of him if he had not.
+
+A gory knife had been found close to the murdered man, and it had been
+recognized by somebody as belonging to Muff Potter--so the story ran.
+And it was said that a belated citizen had come upon Potter washing
+himself in the "branch" about one or two o'clock in the morning, and
+that Potter had at once sneaked off--suspicious circumstances,
+especially the washing which was not a habit with Potter. It was also
+said that the town had been ransacked for this "murderer" (the public
+are not slow in the matter of sifting evidence and arriving at a
+verdict), but that he could not be found. Horsemen had departed down
+all the roads in every direction, and the Sheriff "was confident" that
+he would be captured before night.
+
+All the town was drifting toward the graveyard. Tom's heartbreak
+vanished and he joined the procession, not because he would not a
+thousand times rather go anywhere else, but because an awful,
+unaccountable fascination drew him on. Arrived at the dreadful place,
+he wormed his small body through the crowd and saw the dismal
+spectacle. It seemed to him an age since he was there before. Somebody
+pinched his arm. He turned, and his eyes met Huckleberry's. Then both
+looked elsewhere at once, and wondered if anybody had noticed anything
+in their mutual glance. But everybody was talking, and intent upon the
+grisly spectacle before them.
+
+"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
+grave robbers!" "Muff Potter'll hang for this if they catch him!" This
+was the drift of remark; and the minister said, "It was a judgment; His
+hand is here."
+
+Now Tom shivered from head to heel; for his eye fell upon the stolid
+face of Injun Joe. At this moment the crowd began to sway and struggle,
+and voices shouted, "It's him! it's him! he's coming himself!"
+
+"Who? Who?" from twenty voices.
+
+"Muff Potter!"
+
+"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
+
+People in the branches of the trees over Tom's head said he wasn't
+trying to get away--he only looked doubtful and perplexed.
+
+"Infernal impudence!" said a bystander; "wanted to come and take a
+quiet look at his work, I reckon--didn't expect any company."
+
+The crowd fell apart, now, and the Sheriff came through,
+ostentatiously leading Potter by the arm. The poor fellow's face was
+haggard, and his eyes showed the fear that was upon him. When he stood
+before the murdered man, he shook as with a palsy, and he put his face
+in his hands and burst into tears.
+
+"I didn't do it, friends," he sobbed; "'pon my word and honor I never
+done it."
+
+"Who's accused you?" shouted a voice.
+
+This shot seemed to carry home. Potter lifted his face and looked
+around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
+and exclaimed:
+
+"Oh, Injun Joe, you promised me you'd never--"
+
+"Is that your knife?" and it was thrust before him by the Sheriff.
+
+Potter would have fallen if they had not caught him and eased him to
+the ground. Then he said:
+
+"Something told me 't if I didn't come back and get--" He shuddered;
+then waved his nerveless hand with a vanquished gesture and said, "Tell
+'em, Joe, tell 'em--it ain't any use any more."
+
+Then Huckleberry and Tom stood dumb and staring, and heard the
+stony-hearted liar reel off his serene statement, they expecting every
+moment that the clear sky would deliver God's lightnings upon his head,
+and wondering to see how long the stroke was delayed. And when he had
+finished and still stood alive and whole, their wavering impulse to
+break their oath and save the poor betrayed prisoner's life faded and
+vanished away, for plainly this miscreant had sold himself to Satan and
+it would be fatal to meddle with the property of such a power as that.
+
+"Why didn't you leave? What did you want to come here for?" somebody
+said.
+
+"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
+run away, but I couldn't seem to come anywhere but here." And he fell
+to sobbing again.
+
+Injun Joe repeated his statement, just as calmly, a few minutes
+afterward on the inquest, under oath; and the boys, seeing that the
+lightnings were still withheld, were confirmed in their belief that Joe
+had sold himself to the devil. He was now become, to them, the most
+balefully interesting object they had ever looked upon, and they could
+not take their fascinated eyes from his face.
+
+They inwardly resolved to watch him nights, when opportunity should
+offer, in the hope of getting a glimpse of his dread master.
+
+Injun Joe helped to raise the body of the murdered man and put it in a
+wagon for removal; and it was whispered through the shuddering crowd
+that the wound bled a little! The boys thought that this happy
+circumstance would turn suspicion in the right direction; but they were
+disappointed, for more than one villager remarked:
+
+"It was within three feet of Muff Potter when it done it."
+
+Tom's fearful secret and gnawing conscience disturbed his sleep for as
+much as a week after this; and at breakfast one morning Sid said:
+
+"Tom, you pitch around and talk in your sleep so much that you keep me
+awake half the time."
+
+Tom blanched and dropped his eyes.
+
+"It's a bad sign," said Aunt Polly, gravely. "What you got on your
+mind, Tom?"
+
+"Nothing. Nothing 't I know of." But the boy's hand shook so that he
+spilled his coffee.
+
+"And you do talk such stuff," Sid said. "Last night you said, 'It's
+blood, it's blood, that's what it is!' You said that over and over. And
+you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
+you'll tell?"
+
+Everything was swimming before Tom. There is no telling what might
+have happened, now, but luckily the concern passed out of Aunt Polly's
+face and she came to Tom's relief without knowing it. She said:
+
+"Sho! It's that dreadful murder. I dream about it most every night
+myself. Sometimes I dream it's me that done it."
+
+Mary said she had been affected much the same way. Sid seemed
+satisfied. Tom got out of the presence as quick as he plausibly could,
+and after that he complained of toothache for a week, and tied up his
+jaws every night. He never knew that Sid lay nightly watching, and
+frequently slipped the bandage free and then leaned on his elbow
+listening a good while at a time, and afterward slipped the bandage
+back to its place again. Tom's distress of mind wore off gradually and
+the toothache grew irksome and was discarded. If Sid really managed to
+make anything out of Tom's disjointed mutterings, he kept it to himself.
+
+It seemed to Tom that his schoolmates never would get done holding
+inquests on dead cats, and thus keeping his trouble present to his
+mind. Sid noticed that Tom never was coroner at one of these inquiries,
+though it had been his habit to take the lead in all new enterprises;
+he noticed, too, that Tom never acted as a witness--and that was
+strange; and Sid did not overlook the fact that Tom even showed a
+marked aversion to these inquests, and always avoided them when he
+could. Sid marvelled, but said nothing. However, even inquests went out
+of vogue at last, and ceased to torture Tom's conscience.
+
+Every day or two, during this time of sorrow, Tom watched his
+opportunity and went to the little grated jail-window and smuggled such
+small comforts through to the "murderer" as he could get hold of. The
+jail was a trifling little brick den that stood in a marsh at the edge
+of the village, and no guards were afforded for it; indeed, it was
+seldom occupied. These offerings greatly helped to ease Tom's
+conscience.
+
+The villagers had a strong desire to tar-and-feather Injun Joe and
+ride him on a rail, for body-snatching, but so formidable was his
+character that nobody could be found who was willing to take the lead
+in the matter, so it was dropped. He had been careful to begin both of
+his inquest-statements with the fight, without confessing the
+grave-robbery that preceded it; therefore it was deemed wisest not
+to try the case in the courts at present.
+
+
+
+CHAPTER XII
+
+ONE of the reasons why Tom's mind had drifted away from its secret
+troubles was, that it had found a new and weighty matter to interest
+itself about. Becky Thatcher had stopped coming to school. Tom had
+struggled with his pride a few days, and tried to "whistle her down the
+wind," but failed. He began to find himself hanging around her father's
+house, nights, and feeling very miserable. She was ill. What if she
+should die! There was distraction in the thought. He no longer took an
+interest in war, nor even in piracy. The charm of life was gone; there
+was nothing but dreariness left. He put his hoop away, and his bat;
+there was no joy in them any more. His aunt was concerned. She began to
+try all manner of remedies on him. She was one of those people who are
+infatuated with patent medicines and all new-fangled methods of
+producing health or mending it. She was an inveterate experimenter in
+these things. When something fresh in this line came out she was in a
+fever, right away, to try it; not on herself, for she was never ailing,
+but on anybody else that came handy. She was a subscriber for all the
+"Health" periodicals and phrenological frauds; and the solemn ignorance
+they were inflated with was breath to her nostrils. All the "rot" they
+contained about ventilation, and how to go to bed, and how to get up,
+and what to eat, and what to drink, and how much exercise to take, and
+what frame of mind to keep one's self in, and what sort of clothing to
+wear, was all gospel to her, and she never observed that her
+health-journals of the current month customarily upset everything they
+had recommended the month before. She was as simple-hearted and honest
+as the day was long, and so she was an easy victim. She gathered
+together her quack periodicals and her quack medicines, and thus armed
+with death, went about on her pale horse, metaphorically speaking, with
+"hell following after." But she never suspected that she was not an
+angel of healing and the balm of Gilead in disguise, to the suffering
+neighbors.
+
+The water treatment was new, now, and Tom's low condition was a
+windfall to her. She had him out at daylight every morning, stood him
+up in the woodshed and drowned him with a deluge of cold water; then
+she scrubbed him down with a towel like a file, and so brought him to;
+then she rolled him up in a wet sheet and put him away under blankets
+till she sweated his soul clean and "the yellow stains of it came
+through his pores"--as Tom said.
+
+Yet notwithstanding all this, the boy grew more and more melancholy
+and pale and dejected. She added hot baths, sitz baths, shower baths,
+and plunges. The boy remained as dismal as a hearse. She began to
+assist the water with a slim oatmeal diet and blister-plasters. She
+calculated his capacity as she would a jug's, and filled him up every
+day with quack cure-alls.
+
+Tom had become indifferent to persecution by this time. This phase
+filled the old lady's heart with consternation. This indifference must
+be broken up at any cost. Now she heard of Pain-killer for the first
+time. She ordered a lot at once. She tasted it and was filled with
+gratitude. It was simply fire in a liquid form. She dropped the water
+treatment and everything else, and pinned her faith to Pain-killer. She
+gave Tom a teaspoonful and watched with the deepest anxiety for the
+result. Her troubles were instantly at rest, her soul at peace again;
+for the "indifference" was broken up. The boy could not have shown a
+wilder, heartier interest, if she had built a fire under him.
+
+Tom felt that it was time to wake up; this sort of life might be
+romantic enough, in his blighted condition, but it was getting to have
+too little sentiment and too much distracting variety about it. So he
+thought over various plans for relief, and finally hit pon that of
+professing to be fond of Pain-killer. He asked for it so often that he
+became a nuisance, and his aunt ended by telling him to help himself
+and quit bothering her. If it had been Sid, she would have had no
+misgivings to alloy her delight; but since it was Tom, she watched the
+bottle clandestinely. She found that the medicine did really diminish,
+but it did not occur to her that the boy was mending the health of a
+crack in the sitting-room floor with it.
+
+One day Tom was in the act of dosing the crack when his aunt's yellow
+cat came along, purring, eying the teaspoon avariciously, and begging
+for a taste. Tom said:
+
+"Don't ask for it unless you want it, Peter."
+
+But Peter signified that he did want it.
+
+"You better make sure."
+
+Peter was sure.
+
+"Now you've asked for it, and I'll give it to you, because there ain't
+anything mean about me; but if you find you don't like it, you mustn't
+blame anybody but your own self."
+
+Peter was agreeable. So Tom pried his mouth open and poured down the
+Pain-killer. Peter sprang a couple of yards in the air, and then
+delivered a war-whoop and set off round and round the room, banging
+against furniture, upsetting flower-pots, and making general havoc.
+Next he rose on his hind feet and pranced around, in a frenzy of
+enjoyment, with his head over his shoulder and his voice proclaiming
+his unappeasable happiness. Then he went tearing around the house again
+spreading chaos and destruction in his path. Aunt Polly entered in time
+to see him throw a few double summersets, deliver a final mighty
+hurrah, and sail through the open window, carrying the rest of the
+flower-pots with him. The old lady stood petrified with astonishment,
+peering over her glasses; Tom lay on the floor expiring with laughter.
+
+"Tom, what on earth ails that cat?"
+
+"I don't know, aunt," gasped the boy.
+
+"Why, I never see anything like it. What did make him act so?"
+
+"Deed I don't know, Aunt Polly; cats always act so when they're having
+a good time."
+
+"They do, do they?" There was something in the tone that made Tom
+apprehensive.
+
+"Yes'm. That is, I believe they do."
+
+"You DO?"
+
+"Yes'm."
+
+The old lady was bending down, Tom watching, with interest emphasized
+by anxiety. Too late he divined her "drift." The handle of the telltale
+teaspoon was visible under the bed-valance. Aunt Polly took it, held it
+up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
+usual handle--his ear--and cracked his head soundly with her thimble.
+
+"Now, sir, what did you want to treat that poor dumb beast so, for?"
+
+"I done it out of pity for him--because he hadn't any aunt."
+
+"Hadn't any aunt!--you numskull. What has that got to do with it?"
+
+"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
+roasted his bowels out of him 'thout any more feeling than if he was a
+human!"
+
+Aunt Polly felt a sudden pang of remorse. This was putting the thing
+in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
+too. She began to soften; she felt sorry. Her eyes watered a little,
+and she put her hand on Tom's head and said gently:
+
+"I was meaning for the best, Tom. And, Tom, it DID do you good."
+
+Tom looked up in her face with just a perceptible twinkle peeping
+through his gravity.
+
+"I know you was meaning for the best, aunty, and so was I with Peter.
+It done HIM good, too. I never see him get around so since--"
+
+"Oh, go 'long with you, Tom, before you aggravate me again. And you
+try and see if you can't be a good boy, for once, and you needn't take
+any more medicine."
+
+Tom reached school ahead of time. It was noticed that this strange
+thing had been occurring every day latterly. And now, as usual of late,
+he hung about the gate of the schoolyard instead of playing with his
+comrades. He was sick, he said, and he looked it. He tried to seem to
+be looking everywhere but whither he really was looking--down the road.
+Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
+a moment, and then turned sorrowfully away. When Jeff arrived, Tom
+accosted him; and "led up" warily to opportunities for remark about
+Becky, but the giddy lad never could see the bait. Tom watched and
+watched, hoping whenever a frisking frock came in sight, and hating the
+owner of it as soon as he saw she was not the right one. At last frocks
+ceased to appear, and he dropped hopelessly into the dumps; he entered
+the empty schoolhouse and sat down to suffer. Then one more frock
+passed in at the gate, and Tom's heart gave a great bound. The next
+instant he was out, and "going on" like an Indian; yelling, laughing,
+chasing boys, jumping over the fence at risk of life and limb, throwing
+handsprings, standing on his head--doing all the heroic things he could
+conceive of, and keeping a furtive eye out, all the while, to see if
+Becky Thatcher was noticing. But she seemed to be unconscious of it
+all; she never looked. Could it be possible that she was not aware that
+he was there? He carried his exploits to her immediate vicinity; came
+war-whooping around, snatched a boy's cap, hurled it to the roof of the
+schoolhouse, broke through a group of boys, tumbling them in every
+direction, and fell sprawling, himself, under Becky's nose, almost
+upsetting her--and she turned, with her nose in the air, and he heard
+her say: "Mf! some people think they're mighty smart--always showing
+off!"
+
+Tom's cheeks burned. He gathered himself up and sneaked off, crushed
+and crestfallen.
+
+
+
+CHAPTER XIII
+
+TOM'S mind was made up now. He was gloomy and desperate. He was a
+forsaken, friendless boy, he said; nobody loved him; when they found
+out what they had driven him to, perhaps they would be sorry; he had
+tried to do right and get along, but they would not let him; since
+nothing would do them but to be rid of him, let it be so; and let them
+blame HIM for the consequences--why shouldn't they? What right had the
+friendless to complain? Yes, they had forced him to it at last: he
+would lead a life of crime. There was no choice.
+
+By this time he was far down Meadow Lane, and the bell for school to
+"take up" tinkled faintly upon his ear. He sobbed, now, to think he
+should never, never hear that old familiar sound any more--it was very
+hard, but it was forced on him; since he was driven out into the cold
+world, he must submit--but he forgave them. Then the sobs came thick
+and fast.
+
+Just at this point he met his soul's sworn comrade, Joe Harper
+--hard-eyed, and with evidently a great and dismal purpose in his heart.
+Plainly here were "two souls with but a single thought." Tom, wiping
+his eyes with his sleeve, began to blubber out something about a
+resolution to escape from hard usage and lack of sympathy at home by
+roaming abroad into the great world never to return; and ended by
+hoping that Joe would not forget him.
+
+But it transpired that this was a request which Joe had just been
+going to make of Tom, and had come to hunt him up for that purpose. His
+mother had whipped him for drinking some cream which he had never
+tasted and knew nothing about; it was plain that she was tired of him
+and wished him to go; if she felt that way, there was nothing for him
+to do but succumb; he hoped she would be happy, and never regret having
+driven her poor boy out into the unfeeling world to suffer and die.
+
+As the two boys walked sorrowing along, they made a new compact to
+stand by each other and be brothers and never separate till death
+relieved them of their troubles. Then they began to lay their plans.
+Joe was for being a hermit, and living on crusts in a remote cave, and
+dying, some time, of cold and want and grief; but after listening to
+Tom, he conceded that there were some conspicuous advantages about a
+life of crime, and so he consented to be a pirate.
+
+Three miles below St. Petersburg, at a point where the Mississippi
+River was a trifle over a mile wide, there was a long, narrow, wooded
+island, with a shallow bar at the head of it, and this offered well as
+a rendezvous. It was not inhabited; it lay far over toward the further
+shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
+Island was chosen. Who were to be the subjects of their piracies was a
+matter that did not occur to them. Then they hunted up Huckleberry
+Finn, and he joined them promptly, for all careers were one to him; he
+was indifferent. They presently separated to meet at a lonely spot on
+the river-bank two miles above the village at the favorite hour--which
+was midnight. There was a small log raft there which they meant to
+capture. Each would bring hooks and lines, and such provision as he
+could steal in the most dark and mysterious way--as became outlaws. And
+before the afternoon was done, they had all managed to enjoy the sweet
+glory of spreading the fact that pretty soon the town would "hear
+something." All who got this vague hint were cautioned to "be mum and
+wait."
+
+About midnight Tom arrived with a boiled ham and a few trifles,
+and stopped in a dense undergrowth on a small bluff overlooking the
+meeting-place. It was starlight, and very still. The mighty river lay
+like an ocean at rest. Tom listened a moment, but no sound disturbed the
+quiet. Then he gave a low, distinct whistle. It was answered from under
+the bluff. Tom whistled twice more; these signals were answered in the
+same way. Then a guarded voice said:
+
+"Who goes there?"
+
+"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
+
+"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
+had furnished these titles, from his favorite literature.
+
+"'Tis well. Give the countersign."
+
+Two hoarse whispers delivered the same awful word simultaneously to
+the brooding night:
+
+"BLOOD!"
+
+Then Tom tumbled his ham over the bluff and let himself down after it,
+tearing both skin and clothes to some extent in the effort. There was
+an easy, comfortable path along the shore under the bluff, but it
+lacked the advantages of difficulty and danger so valued by a pirate.
+
+The Terror of the Seas had brought a side of bacon, and had about worn
+himself out with getting it there. Finn the Red-Handed had stolen a
+skillet and a quantity of half-cured leaf tobacco, and had also brought
+a few corn-cobs to make pipes with. But none of the pirates smoked or
+"chewed" but himself. The Black Avenger of the Spanish Main said it
+would never do to start without some fire. That was a wise thought;
+matches were hardly known there in that day. They saw a fire
+smouldering upon a great raft a hundred yards above, and they went
+stealthily thither and helped themselves to a chunk. They made an
+imposing adventure of it, saying, "Hist!" every now and then, and
+suddenly halting with finger on lip; moving with hands on imaginary
+dagger-hilts; and giving orders in dismal whispers that if "the foe"
+stirred, to "let him have it to the hilt," because "dead men tell no
+tales." They knew well enough that the raftsmen were all down at the
+village laying in stores or having a spree, but still that was no
+excuse for their conducting this thing in an unpiratical way.
+
+They shoved off, presently, Tom in command, Huck at the after oar and
+Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
+arms, and gave his orders in a low, stern whisper:
+
+"Luff, and bring her to the wind!"
+
+"Aye-aye, sir!"
+
+"Steady, steady-y-y-y!"
+
+"Steady it is, sir!"
+
+"Let her go off a point!"
+
+"Point it is, sir!"
+
+As the boys steadily and monotonously drove the raft toward mid-stream
+it was no doubt understood that these orders were given only for
+"style," and were not intended to mean anything in particular.
+
+"What sail's she carrying?"
+
+"Courses, tops'ls, and flying-jib, sir."
+
+"Send the r'yals up! Lay out aloft, there, half a dozen of ye
+--foretopmaststuns'l! Lively, now!"
+
+"Aye-aye, sir!"
+
+"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
+
+"Aye-aye, sir!"
+
+"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
+port! NOW, men! With a will! Stead-y-y-y!"
+
+"Steady it is, sir!"
+
+The raft drew beyond the middle of the river; the boys pointed her
+head right, and then lay on their oars. The river was not high, so
+there was not more than a two or three mile current. Hardly a word was
+said during the next three-quarters of an hour. Now the raft was
+passing before the distant town. Two or three glimmering lights showed
+where it lay, peacefully sleeping, beyond the vague vast sweep of
+star-gemmed water, unconscious of the tremendous event that was happening.
+The Black Avenger stood still with folded arms, "looking his last" upon
+the scene of his former joys and his later sufferings, and wishing
+"she" could see him now, abroad on the wild sea, facing peril and death
+with dauntless heart, going to his doom with a grim smile on his lips.
+It was but a small strain on his imagination to remove Jackson's Island
+beyond eyeshot of the village, and so he "looked his last" with a
+broken and satisfied heart. The other pirates were looking their last,
+too; and they all looked so long that they came near letting the
+current drift them out of the range of the island. But they discovered
+the danger in time, and made shift to avert it. About two o'clock in
+the morning the raft grounded on the bar two hundred yards above the
+head of the island, and they waded back and forth until they had landed
+their freight. Part of the little raft's belongings consisted of an old
+sail, and this they spread over a nook in the bushes for a tent to
+shelter their provisions; but they themselves would sleep in the open
+air in good weather, as became outlaws.
+
+They built a fire against the side of a great log twenty or thirty
+steps within the sombre depths of the forest, and then cooked some
+bacon in the frying-pan for supper, and used up half of the corn "pone"
+stock they had brought. It seemed glorious sport to be feasting in that
+wild, free way in the virgin forest of an unexplored and uninhabited
+island, far from the haunts of men, and they said they never would
+return to civilization. The climbing fire lit up their faces and threw
+its ruddy glare upon the pillared tree-trunks of their forest temple,
+and upon the varnished foliage and festooning vines.
+
+When the last crisp slice of bacon was gone, and the last allowance of
+corn pone devoured, the boys stretched themselves out on the grass,
+filled with contentment. They could have found a cooler place, but they
+would not deny themselves such a romantic feature as the roasting
+camp-fire.
+
+"AIN'T it gay?" said Joe.
+
+"It's NUTS!" said Tom. "What would the boys say if they could see us?"
+
+"Say? Well, they'd just die to be here--hey, Hucky!"
+
+"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
+nothing better'n this. I don't ever get enough to eat, gen'ally--and
+here they can't come and pick at a feller and bullyrag him so."
+
+"It's just the life for me," said Tom. "You don't have to get up,
+mornings, and you don't have to go to school, and wash, and all that
+blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
+when he's ashore, but a hermit HE has to be praying considerable, and
+then he don't have any fun, anyway, all by himself that way."
+
+"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
+you know. I'd a good deal rather be a pirate, now that I've tried it."
+
+"You see," said Tom, "people don't go much on hermits, nowadays, like
+they used to in old times, but a pirate's always respected. And a
+hermit's got to sleep on the hardest place he can find, and put
+sackcloth and ashes on his head, and stand out in the rain, and--"
+
+"What does he put sackcloth and ashes on his head for?" inquired Huck.
+
+"I dono. But they've GOT to do it. Hermits always do. You'd have to do
+that if you was a hermit."
+
+"Dern'd if I would," said Huck.
+
+"Well, what would you do?"
+
+"I dono. But I wouldn't do that."
+
+"Why, Huck, you'd HAVE to. How'd you get around it?"
+
+"Why, I just wouldn't stand it. I'd run away."
+
+"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
+a disgrace."
+
+The Red-Handed made no response, being better employed. He had
+finished gouging out a cob, and now he fitted a weed stem to it, loaded
+it with tobacco, and was pressing a coal to the charge and blowing a
+cloud of fragrant smoke--he was in the full bloom of luxurious
+contentment. The other pirates envied him this majestic vice, and
+secretly resolved to acquire it shortly. Presently Huck said:
+
+"What does pirates have to do?"
+
+Tom said:
+
+"Oh, they have just a bully time--take ships and burn them, and get
+the money and bury it in awful places in their island where there's
+ghosts and things to watch it, and kill everybody in the ships--make
+'em walk a plank."
+
+"And they carry the women to the island," said Joe; "they don't kill
+the women."
+
+"No," assented Tom, "they don't kill the women--they're too noble. And
+the women's always beautiful, too.
+
+"And don't they wear the bulliest clothes! Oh no! All gold and silver
+and di'monds," said Joe, with enthusiasm.
+
+"Who?" said Huck.
+
+"Why, the pirates."
+
+Huck scanned his own clothing forlornly.
+
+"I reckon I ain't dressed fitten for a pirate," said he, with a
+regretful pathos in his voice; "but I ain't got none but these."
+
+But the other boys told him the fine clothes would come fast enough,
+after they should have begun their adventures. They made him understand
+that his poor rags would do to begin with, though it was customary for
+wealthy pirates to start with a proper wardrobe.
+
+Gradually their talk died out and drowsiness began to steal upon the
+eyelids of the little waifs. The pipe dropped from the fingers of the
+Red-Handed, and he slept the sleep of the conscience-free and the
+weary. The Terror of the Seas and the Black Avenger of the Spanish Main
+had more difficulty in getting to sleep. They said their prayers
+inwardly, and lying down, since there was nobody there with authority
+to make them kneel and recite aloud; in truth, they had a mind not to
+say them at all, but they were afraid to proceed to such lengths as
+that, lest they might call down a sudden and special thunderbolt from
+heaven. Then at once they reached and hovered upon the imminent verge
+of sleep--but an intruder came, now, that would not "down." It was
+conscience. They began to feel a vague fear that they had been doing
+wrong to run away; and next they thought of the stolen meat, and then
+the real torture came. They tried to argue it away by reminding
+conscience that they had purloined sweetmeats and apples scores of
+times; but conscience was not to be appeased by such thin
+plausibilities; it seemed to them, in the end, that there was no
+getting around the stubborn fact that taking sweetmeats was only
+"hooking," while taking bacon and hams and such valuables was plain
+simple stealing--and there was a command against that in the Bible. So
+they inwardly resolved that so long as they remained in the business,
+their piracies should not again be sullied with the crime of stealing.
+Then conscience granted a truce, and these curiously inconsistent
+pirates fell peacefully to sleep.
+
+
+
+CHAPTER XIV
+
+WHEN Tom awoke in the morning, he wondered where he was. He sat up and
+rubbed his eyes and looked around. Then he comprehended. It was the
+cool gray dawn, and there was a delicious sense of repose and peace in
+the deep pervading calm and silence of the woods. Not a leaf stirred;
+not a sound obtruded upon great Nature's meditation. Beaded dewdrops
+stood upon the leaves and grasses. A white layer of ashes covered the
+fire, and a thin blue breath of smoke rose straight into the air. Joe
+and Huck still slept.
+
+Now, far away in the woods a bird called; another answered; presently
+the hammering of a woodpecker was heard. Gradually the cool dim gray of
+the morning whitened, and as gradually sounds multiplied and life
+manifested itself. The marvel of Nature shaking off sleep and going to
+work unfolded itself to the musing boy. A little green worm came
+crawling over a dewy leaf, lifting two-thirds of his body into the air
+from time to time and "sniffing around," then proceeding again--for he
+was measuring, Tom said; and when the worm approached him, of its own
+accord, he sat as still as a stone, with his hopes rising and falling,
+by turns, as the creature still came toward him or seemed inclined to
+go elsewhere; and when at last it considered a painful moment with its
+curved body in the air and then came decisively down upon Tom's leg and
+began a journey over him, his whole heart was glad--for that meant that
+he was going to have a new suit of clothes--without the shadow of a
+doubt a gaudy piratical uniform. Now a procession of ants appeared,
+from nowhere in particular, and went about their labors; one struggled
+manfully by with a dead spider five times as big as itself in its arms,
+and lugged it straight up a tree-trunk. A brown spotted lady-bug
+climbed the dizzy height of a grass blade, and Tom bent down close to
+it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
+your children's alone," and she took wing and went off to see about it
+--which did not surprise the boy, for he knew of old that this insect was
+credulous about conflagrations, and he had practised upon its
+simplicity more than once. A tumblebug came next, heaving sturdily at
+its ball, and Tom touched the creature, to see it shut its legs against
+its body and pretend to be dead. The birds were fairly rioting by this
+time. A catbird, the Northern mocker, lit in a tree over Tom's head,
+and trilled out her imitations of her neighbors in a rapture of
+enjoyment; then a shrill jay swept down, a flash of blue flame, and
+stopped on a twig almost within the boy's reach, cocked his head to one
+side and eyed the strangers with a consuming curiosity; a gray squirrel
+and a big fellow of the "fox" kind came skurrying along, sitting up at
+intervals to inspect and chatter at the boys, for the wild things had
+probably never seen a human being before and scarcely knew whether to
+be afraid or not. All Nature was wide awake and stirring, now; long
+lances of sunlight pierced down through the dense foliage far and near,
+and a few butterflies came fluttering upon the scene.
+
+Tom stirred up the other pirates and they all clattered away with a
+shout, and in a minute or two were stripped and chasing after and
+tumbling over each other in the shallow limpid water of the white
+sandbar. They felt no longing for the little village sleeping in the
+distance beyond the majestic waste of water. A vagrant current or a
+slight rise in the river had carried off their raft, but this only
+gratified them, since its going was something like burning the bridge
+between them and civilization.
+
+They came back to camp wonderfully refreshed, glad-hearted, and
+ravenous; and they soon had the camp-fire blazing up again. Huck found
+a spring of clear cold water close by, and the boys made cups of broad
+oak or hickory leaves, and felt that water, sweetened with such a
+wildwood charm as that, would be a good enough substitute for coffee.
+While Joe was slicing bacon for breakfast, Tom and Huck asked him to
+hold on a minute; they stepped to a promising nook in the river-bank
+and threw in their lines; almost immediately they had reward. Joe had
+not had time to get impatient before they were back again with some
+handsome bass, a couple of sun-perch and a small catfish--provisions
+enough for quite a family. They fried the fish with the bacon, and were
+astonished; for no fish had ever seemed so delicious before. They did
+not know that the quicker a fresh-water fish is on the fire after he is
+caught the better he is; and they reflected little upon what a sauce
+open-air sleeping, open-air exercise, bathing, and a large ingredient
+of hunger make, too.
+
+They lay around in the shade, after breakfast, while Huck had a smoke,
+and then went off through the woods on an exploring expedition. They
+tramped gayly along, over decaying logs, through tangled underbrush,
+among solemn monarchs of the forest, hung from their crowns to the
+ground with a drooping regalia of grape-vines. Now and then they came
+upon snug nooks carpeted with grass and jeweled with flowers.
+
+They found plenty of things to be delighted with, but nothing to be
+astonished at. They discovered that the island was about three miles
+long and a quarter of a mile wide, and that the shore it lay closest to
+was only separated from it by a narrow channel hardly two hundred yards
+wide. They took a swim about every hour, so it was close upon the
+middle of the afternoon when they got back to camp. They were too
+hungry to stop to fish, but they fared sumptuously upon cold ham, and
+then threw themselves down in the shade to talk. But the talk soon
+began to drag, and then died. The stillness, the solemnity that brooded
+in the woods, and the sense of loneliness, began to tell upon the
+spirits of the boys. They fell to thinking. A sort of undefined longing
+crept upon them. This took dim shape, presently--it was budding
+homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
+and empty hogsheads. But they were all ashamed of their weakness, and
+none was brave enough to speak his thought.
+
+For some time, now, the boys had been dully conscious of a peculiar
+sound in the distance, just as one sometimes is of the ticking of a
+clock which he takes no distinct note of. But now this mysterious sound
+became more pronounced, and forced a recognition. The boys started,
+glanced at each other, and then each assumed a listening attitude.
+There was a long silence, profound and unbroken; then a deep, sullen
+boom came floating down out of the distance.
+
+"What is it!" exclaimed Joe, under his breath.
+
+"I wonder," said Tom in a whisper.
+
+"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
+
+"Hark!" said Tom. "Listen--don't talk."
+
+They waited a time that seemed an age, and then the same muffled boom
+troubled the solemn hush.
+
+"Let's go and see."
+
+They sprang to their feet and hurried to the shore toward the town.
+They parted the bushes on the bank and peered out over the water. The
+little steam ferryboat was about a mile below the village, drifting
+with the current. Her broad deck seemed crowded with people. There were
+a great many skiffs rowing about or floating with the stream in the
+neighborhood of the ferryboat, but the boys could not determine what
+the men in them were doing. Presently a great jet of white smoke burst
+from the ferryboat's side, and as it expanded and rose in a lazy cloud,
+that same dull throb of sound was borne to the listeners again.
+
+"I know now!" exclaimed Tom; "somebody's drownded!"
+
+"That's it!" said Huck; "they done that last summer, when Bill Turner
+got drownded; they shoot a cannon over the water, and that makes him
+come up to the top. Yes, and they take loaves of bread and put
+quicksilver in 'em and set 'em afloat, and wherever there's anybody
+that's drownded, they'll float right there and stop."
+
+"Yes, I've heard about that," said Joe. "I wonder what makes the bread
+do that."
+
+"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
+what they SAY over it before they start it out."
+
+"But they don't say anything over it," said Huck. "I've seen 'em and
+they don't."
+
+"Well, that's funny," said Tom. "But maybe they say it to themselves.
+Of COURSE they do. Anybody might know that."
+
+The other boys agreed that there was reason in what Tom said, because
+an ignorant lump of bread, uninstructed by an incantation, could not be
+expected to act very intelligently when set upon an errand of such
+gravity.
+
+"By jings, I wish I was over there, now," said Joe.
+
+"I do too" said Huck "I'd give heaps to know who it is."
+
+The boys still listened and watched. Presently a revealing thought
+flashed through Tom's mind, and he exclaimed:
+
+"Boys, I know who's drownded--it's us!"
+
+They felt like heroes in an instant. Here was a gorgeous triumph; they
+were missed; they were mourned; hearts were breaking on their account;
+tears were being shed; accusing memories of unkindness to these poor
+lost lads were rising up, and unavailing regrets and remorse were being
+indulged; and best of all, the departed were the talk of the whole
+town, and the envy of all the boys, as far as this dazzling notoriety
+was concerned. This was fine. It was worth while to be a pirate, after
+all.
+
+As twilight drew on, the ferryboat went back to her accustomed
+business and the skiffs disappeared. The pirates returned to camp. They
+were jubilant with vanity over their new grandeur and the illustrious
+trouble they were making. They caught fish, cooked supper and ate it,
+and then fell to guessing at what the village was thinking and saying
+about them; and the pictures they drew of the public distress on their
+account were gratifying to look upon--from their point of view. But
+when the shadows of night closed them in, they gradually ceased to
+talk, and sat gazing into the fire, with their minds evidently
+wandering elsewhere. The excitement was gone, now, and Tom and Joe
+could not keep back thoughts of certain persons at home who were not
+enjoying this fine frolic as much as they were. Misgivings came; they
+grew troubled and unhappy; a sigh or two escaped, unawares. By and by
+Joe timidly ventured upon a roundabout "feeler" as to how the others
+might look upon a return to civilization--not right now, but--
+
+Tom withered him with derision! Huck, being uncommitted as yet, joined
+in with Tom, and the waverer quickly "explained," and was glad to get
+out of the scrape with as little taint of chicken-hearted homesickness
+clinging to his garments as he could. Mutiny was effectually laid to
+rest for the moment.
+
+As the night deepened, Huck began to nod, and presently to snore. Joe
+followed next. Tom lay upon his elbow motionless, for some time,
+watching the two intently. At last he got up cautiously, on his knees,
+and went searching among the grass and the flickering reflections flung
+by the camp-fire. He picked up and inspected several large
+semi-cylinders of the thin white bark of a sycamore, and finally chose
+two which seemed to suit him. Then he knelt by the fire and painfully
+wrote something upon each of these with his "red keel"; one he rolled up
+and put in his jacket pocket, and the other he put in Joe's hat and
+removed it to a little distance from the owner. And he also put into the
+hat certain schoolboy treasures of almost inestimable value--among them
+a lump of chalk, an India-rubber ball, three fishhooks, and one of that
+kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
+way cautiously among the trees till he felt that he was out of hearing,
+and straightway broke into a keen run in the direction of the sandbar.
+
+
+
+CHAPTER XV
+
+A FEW minutes later Tom was in the shoal water of the bar, wading
+toward the Illinois shore. Before the depth reached his middle he was
+half-way over; the current would permit no more wading, now, so he
+struck out confidently to swim the remaining hundred yards. He swam
+quartering upstream, but still was swept downward rather faster than he
+had expected. However, he reached the shore finally, and drifted along
+till he found a low place and drew himself out. He put his hand on his
+jacket pocket, found his piece of bark safe, and then struck through
+the woods, following the shore, with streaming garments. Shortly before
+ten o'clock he came out into an open place opposite the village, and
+saw the ferryboat lying in the shadow of the trees and the high bank.
+Everything was quiet under the blinking stars. He crept down the bank,
+watching with all his eyes, slipped into the water, swam three or four
+strokes and climbed into the skiff that did "yawl" duty at the boat's
+stern. He laid himself down under the thwarts and waited, panting.
+
+Presently the cracked bell tapped and a voice gave the order to "cast
+off." A minute or two later the skiff's head was standing high up,
+against the boat's swell, and the voyage was begun. Tom felt happy in
+his success, for he knew it was the boat's last trip for the night. At
+the end of a long twelve or fifteen minutes the wheels stopped, and Tom
+slipped overboard and swam ashore in the dusk, landing fifty yards
+downstream, out of danger of possible stragglers.
+
+He flew along unfrequented alleys, and shortly found himself at his
+aunt's back fence. He climbed over, approached the "ell," and looked in
+at the sitting-room window, for a light was burning there. There sat
+Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
+talking. They were by the bed, and the bed was between them and the
+door. Tom went to the door and began to softly lift the latch; then he
+pressed gently and the door yielded a crack; he continued pushing
+cautiously, and quaking every time it creaked, till he judged he might
+squeeze through on his knees; so he put his head through and began,
+warily.
+
+"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
+"Why, that door's open, I believe. Why, of course it is. No end of
+strange things now. Go 'long and shut it, Sid."
+
+Tom disappeared under the bed just in time. He lay and "breathed"
+himself for a time, and then crept to where he could almost touch his
+aunt's foot.
+
+"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
+--only mischEEvous. Only just giddy, and harum-scarum, you know. He
+warn't any more responsible than a colt. HE never meant any harm, and
+he was the best-hearted boy that ever was"--and she began to cry.
+
+"It was just so with my Joe--always full of his devilment, and up to
+every kind of mischief, but he was just as unselfish and kind as he
+could be--and laws bless me, to think I went and whipped him for taking
+that cream, never once recollecting that I throwed it out myself
+because it was sour, and I never to see him again in this world, never,
+never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
+would break.
+
+"I hope Tom's better off where he is," said Sid, "but if he'd been
+better in some ways--"
+
+"SID!" Tom felt the glare of the old lady's eye, though he could not
+see it. "Not a word against my Tom, now that he's gone! God'll take
+care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
+know how to give him up! I don't know how to give him up! He was such a
+comfort to me, although he tormented my old heart out of me, 'most."
+
+"The Lord giveth and the Lord hath taken away--Blessed be the name of
+the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
+Joe busted a firecracker right under my nose and I knocked him
+sprawling. Little did I know then, how soon--Oh, if it was to do over
+again I'd hug him and bless him for it."
+
+"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
+exactly how you feel. No longer ago than yesterday noon, my Tom took
+and filled the cat full of Pain-killer, and I did think the cretur
+would tear the house down. And God forgive me, I cracked Tom's head
+with my thimble, poor boy, poor dead boy. But he's out of all his
+troubles now. And the last words I ever heard him say was to reproach--"
+
+But this memory was too much for the old lady, and she broke entirely
+down. Tom was snuffling, now, himself--and more in pity of himself than
+anybody else. He could hear Mary crying, and putting in a kindly word
+for him from time to time. He began to have a nobler opinion of himself
+than ever before. Still, he was sufficiently touched by his aunt's
+grief to long to rush out from under the bed and overwhelm her with
+joy--and the theatrical gorgeousness of the thing appealed strongly to
+his nature, too, but he resisted and lay still.
+
+He went on listening, and gathered by odds and ends that it was
+conjectured at first that the boys had got drowned while taking a swim;
+then the small raft had been missed; next, certain boys said the
+missing lads had promised that the village should "hear something"
+soon; the wise-heads had "put this and that together" and decided that
+the lads had gone off on that raft and would turn up at the next town
+below, presently; but toward noon the raft had been found, lodged
+against the Missouri shore some five or six miles below the village
+--and then hope perished; they must be drowned, else hunger would have
+driven them home by nightfall if not sooner. It was believed that the
+search for the bodies had been a fruitless effort merely because the
+drowning must have occurred in mid-channel, since the boys, being good
+swimmers, would otherwise have escaped to shore. This was Wednesday
+night. If the bodies continued missing until Sunday, all hope would be
+given over, and the funerals would be preached on that morning. Tom
+shuddered.
+
+Mrs. Harper gave a sobbing good-night and turned to go. Then with a
+mutual impulse the two bereaved women flung themselves into each
+other's arms and had a good, consoling cry, and then parted. Aunt Polly
+was tender far beyond her wont, in her good-night to Sid and Mary. Sid
+snuffled a bit and Mary went off crying with all her heart.
+
+Aunt Polly knelt down and prayed for Tom so touchingly, so
+appealingly, and with such measureless love in her words and her old
+trembling voice, that he was weltering in tears again, long before she
+was through.
+
+He had to keep still long after she went to bed, for she kept making
+broken-hearted ejaculations from time to time, tossing unrestfully, and
+turning over. But at last she was still, only moaning a little in her
+sleep. Now the boy stole out, rose gradually by the bedside, shaded the
+candle-light with his hand, and stood regarding her. His heart was full
+of pity for her. He took out his sycamore scroll and placed it by the
+candle. But something occurred to him, and he lingered considering. His
+face lighted with a happy solution of his thought; he put the bark
+hastily in his pocket. Then he bent over and kissed the faded lips, and
+straightway made his stealthy exit, latching the door behind him.
+
+He threaded his way back to the ferry landing, found nobody at large
+there, and walked boldly on board the boat, for he knew she was
+tenantless except that there was a watchman, who always turned in and
+slept like a graven image. He untied the skiff at the stern, slipped
+into it, and was soon rowing cautiously upstream. When he had pulled a
+mile above the village, he started quartering across and bent himself
+stoutly to his work. He hit the landing on the other side neatly, for
+this was a familiar bit of work to him. He was moved to capture the
+skiff, arguing that it might be considered a ship and therefore
+legitimate prey for a pirate, but he knew a thorough search would be
+made for it and that might end in revelations. So he stepped ashore and
+entered the woods.
+
+He sat down and took a long rest, torturing himself meanwhile to keep
+awake, and then started warily down the home-stretch. The night was far
+spent. It was broad daylight before he found himself fairly abreast the
+island bar. He rested again until the sun was well up and gilding the
+great river with its splendor, and then he plunged into the stream. A
+little later he paused, dripping, upon the threshold of the camp, and
+heard Joe say:
+
+"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
+knows that would be a disgrace to a pirate, and Tom's too proud for
+that sort of thing. He's up to something or other. Now I wonder what?"
+
+"Well, the things is ours, anyway, ain't they?"
+
+"Pretty near, but not yet, Huck. The writing says they are if he ain't
+back here to breakfast."
+
+"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
+grandly into camp.
+
+A sumptuous breakfast of bacon and fish was shortly provided, and as
+the boys set to work upon it, Tom recounted (and adorned) his
+adventures. They were a vain and boastful company of heroes when the
+tale was done. Then Tom hid himself away in a shady nook to sleep till
+noon, and the other pirates got ready to fish and explore.
+
+
+
+CHAPTER XVI
+
+AFTER dinner all the gang turned out to hunt for turtle eggs on the
+bar. They went about poking sticks into the sand, and when they found a
+soft place they went down on their knees and dug with their hands.
+Sometimes they would take fifty or sixty eggs out of one hole. They
+were perfectly round white things a trifle smaller than an English
+walnut. They had a famous fried-egg feast that night, and another on
+Friday morning.
+
+After breakfast they went whooping and prancing out on the bar, and
+chased each other round and round, shedding clothes as they went, until
+they were naked, and then continued the frolic far away up the shoal
+water of the bar, against the stiff current, which latter tripped their
+legs from under them from time to time and greatly increased the fun.
+And now and then they stooped in a group and splashed water in each
+other's faces with their palms, gradually approaching each other, with
+averted faces to avoid the strangling sprays, and finally gripping and
+struggling till the best man ducked his neighbor, and then they all
+went under in a tangle of white legs and arms and came up blowing,
+sputtering, laughing, and gasping for breath at one and the same time.
+
+When they were well exhausted, they would run out and sprawl on the
+dry, hot sand, and lie there and cover themselves up with it, and by
+and by break for the water again and go through the original
+performance once more. Finally it occurred to them that their naked
+skin represented flesh-colored "tights" very fairly; so they drew a
+ring in the sand and had a circus--with three clowns in it, for none
+would yield this proudest post to his neighbor.
+
+Next they got their marbles and played "knucks" and "ring-taw" and
+"keeps" till that amusement grew stale. Then Joe and Huck had another
+swim, but Tom would not venture, because he found that in kicking off
+his trousers he had kicked his string of rattlesnake rattles off his
+ankle, and he wondered how he had escaped cramp so long without the
+protection of this mysterious charm. He did not venture again until he
+had found it, and by that time the other boys were tired and ready to
+rest. They gradually wandered apart, dropped into the "dumps," and fell
+to gazing longingly across the wide river to where the village lay
+drowsing in the sun. Tom found himself writing "BECKY" in the sand with
+his big toe; he scratched it out, and was angry with himself for his
+weakness. But he wrote it again, nevertheless; he could not help it. He
+erased it once more and then took himself out of temptation by driving
+the other boys together and joining them.
+
+But Joe's spirits had gone down almost beyond resurrection. He was so
+homesick that he could hardly endure the misery of it. The tears lay
+very near the surface. Huck was melancholy, too. Tom was downhearted,
+but tried hard not to show it. He had a secret which he was not ready
+to tell, yet, but if this mutinous depression was not broken up soon,
+he would have to bring it out. He said, with a great show of
+cheerfulness:
+
+"I bet there's been pirates on this island before, boys. We'll explore
+it again. They've hid treasures here somewhere. How'd you feel to light
+on a rotten chest full of gold and silver--hey?"
+
+But it roused only faint enthusiasm, which faded out, with no reply.
+Tom tried one or two other seductions; but they failed, too. It was
+discouraging work. Joe sat poking up the sand with a stick and looking
+very gloomy. Finally he said:
+
+"Oh, boys, let's give it up. I want to go home. It's so lonesome."
+
+"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
+the fishing that's here."
+
+"I don't care for fishing. I want to go home."
+
+"But, Joe, there ain't such another swimming-place anywhere."
+
+"Swimming's no good. I don't seem to care for it, somehow, when there
+ain't anybody to say I sha'n't go in. I mean to go home."
+
+"Oh, shucks! Baby! You want to see your mother, I reckon."
+
+"Yes, I DO want to see my mother--and you would, too, if you had one.
+I ain't any more baby than you are." And Joe snuffled a little.
+
+"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
+Poor thing--does it want to see its mother? And so it shall. You like
+it here, don't you, Huck? We'll stay, won't we?"
+
+Huck said, "Y-e-s"--without any heart in it.
+
+"I'll never speak to you again as long as I live," said Joe, rising.
+"There now!" And he moved moodily away and began to dress himself.
+
+"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
+laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
+We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
+get along without him, per'aps."
+
+But Tom was uneasy, nevertheless, and was alarmed to see Joe go
+sullenly on with his dressing. And then it was discomforting to see
+Huck eying Joe's preparations so wistfully, and keeping up such an
+ominous silence. Presently, without a parting word, Joe began to wade
+off toward the Illinois shore. Tom's heart began to sink. He glanced at
+Huck. Huck could not bear the look, and dropped his eyes. Then he said:
+
+"I want to go, too, Tom. It was getting so lonesome anyway, and now
+it'll be worse. Let's us go, too, Tom."
+
+"I won't! You can all go, if you want to. I mean to stay."
+
+"Tom, I better go."
+
+"Well, go 'long--who's hendering you."
+
+Huck began to pick up his scattered clothes. He said:
+
+"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
+you when we get to shore."
+
+"Well, you'll wait a blame long time, that's all."
+
+Huck started sorrowfully away, and Tom stood looking after him, with a
+strong desire tugging at his heart to yield his pride and go along too.
+He hoped the boys would stop, but they still waded slowly on. It
+suddenly dawned on Tom that it was become very lonely and still. He
+made one final struggle with his pride, and then darted after his
+comrades, yelling:
+
+"Wait! Wait! I want to tell you something!"
+
+They presently stopped and turned around. When he got to where they
+were, he began unfolding his secret, and they listened moodily till at
+last they saw the "point" he was driving at, and then they set up a
+war-whoop of applause and said it was "splendid!" and said if he had
+told them at first, they wouldn't have started away. He made a plausible
+excuse; but his real reason had been the fear that not even the secret
+would keep them with him any very great length of time, and so he had
+meant to hold it in reserve as a last seduction.
+
+The lads came gayly back and went at their sports again with a will,
+chattering all the time about Tom's stupendous plan and admiring the
+genius of it. After a dainty egg and fish dinner, Tom said he wanted to
+learn to smoke, now. Joe caught at the idea and said he would like to
+try, too. So Huck made pipes and filled them. These novices had never
+smoked anything before but cigars made of grape-vine, and they "bit"
+the tongue, and were not considered manly anyway.
+
+Now they stretched themselves out on their elbows and began to puff,
+charily, and with slender confidence. The smoke had an unpleasant
+taste, and they gagged a little, but Tom said:
+
+"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
+long ago."
+
+"So would I," said Joe. "It's just nothing."
+
+"Why, many a time I've looked at people smoking, and thought well I
+wish I could do that; but I never thought I could," said Tom.
+
+"That's just the way with me, hain't it, Huck? You've heard me talk
+just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
+
+"Yes--heaps of times," said Huck.
+
+"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
+slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
+Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
+Huck, 'bout me saying that?"
+
+"Yes, that's so," said Huck. "That was the day after I lost a white
+alley. No, 'twas the day before."
+
+"There--I told you so," said Tom. "Huck recollects it."
+
+"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
+sick."
+
+"Neither do I," said Tom. "I could smoke it all day. But I bet you
+Jeff Thatcher couldn't."
+
+"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
+try it once. HE'D see!"
+
+"I bet he would. And Johnny Miller--I wish could see Johnny Miller
+tackle it once."
+
+"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
+more do this than nothing. Just one little snifter would fetch HIM."
+
+"'Deed it would, Joe. Say--I wish the boys could see us now."
+
+"So do I."
+
+"Say--boys, don't say anything about it, and some time when they're
+around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
+And you'll say, kind of careless like, as if it warn't anything, you'll
+say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
+very good.' And I'll say, 'Oh, that's all right, if it's STRONG
+enough.' And then you'll out with the pipes, and we'll light up just as
+ca'm, and then just see 'em look!"
+
+"By jings, that'll be gay, Tom! I wish it was NOW!"
+
+"So do I! And when we tell 'em we learned when we was off pirating,
+won't they wish they'd been along?"
+
+"Oh, I reckon not! I'll just BET they will!"
+
+So the talk ran on. But presently it began to flag a trifle, and grow
+disjointed. The silences widened; the expectoration marvellously
+increased. Every pore inside the boys' cheeks became a spouting
+fountain; they could scarcely bail out the cellars under their tongues
+fast enough to prevent an inundation; little overflowings down their
+throats occurred in spite of all they could do, and sudden retchings
+followed every time. Both boys were looking very pale and miserable,
+now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
+Both fountains were going furiously and both pumps bailing with might
+and main. Joe said feebly:
+
+"I've lost my knife. I reckon I better go and find it."
+
+Tom said, with quivering lips and halting utterance:
+
+"I'll help you. You go over that way and I'll hunt around by the
+spring. No, you needn't come, Huck--we can find it."
+
+So Huck sat down again, and waited an hour. Then he found it lonesome,
+and went to find his comrades. They were wide apart in the woods, both
+very pale, both fast asleep. But something informed him that if they
+had had any trouble they had got rid of it.
+
+They were not talkative at supper that night. They had a humble look,
+and when Huck prepared his pipe after the meal and was going to prepare
+theirs, they said no, they were not feeling very well--something they
+ate at dinner had disagreed with them.
+
+About midnight Joe awoke, and called the boys. There was a brooding
+oppressiveness in the air that seemed to bode something. The boys
+huddled themselves together and sought the friendly companionship of
+the fire, though the dull dead heat of the breathless atmosphere was
+stifling. They sat still, intent and waiting. The solemn hush
+continued. Beyond the light of the fire everything was swallowed up in
+the blackness of darkness. Presently there came a quivering glow that
+vaguely revealed the foliage for a moment and then vanished. By and by
+another came, a little stronger. Then another. Then a faint moan came
+sighing through the branches of the forest and the boys felt a fleeting
+breath upon their cheeks, and shuddered with the fancy that the Spirit
+of the Night had gone by. There was a pause. Now a weird flash turned
+night into day and showed every little grass-blade, separate and
+distinct, that grew about their feet. And it showed three white,
+startled faces, too. A deep peal of thunder went rolling and tumbling
+down the heavens and lost itself in sullen rumblings in the distance. A
+sweep of chilly air passed by, rustling all the leaves and snowing the
+flaky ashes broadcast about the fire. Another fierce glare lit up the
+forest and an instant crash followed that seemed to rend the tree-tops
+right over the boys' heads. They clung together in terror, in the thick
+gloom that followed. A few big rain-drops fell pattering upon the
+leaves.
+
+"Quick! boys, go for the tent!" exclaimed Tom.
+
+They sprang away, stumbling over roots and among vines in the dark, no
+two plunging in the same direction. A furious blast roared through the
+trees, making everything sing as it went. One blinding flash after
+another came, and peal on peal of deafening thunder. And now a
+drenching rain poured down and the rising hurricane drove it in sheets
+along the ground. The boys cried out to each other, but the roaring
+wind and the booming thunder-blasts drowned their voices utterly.
+However, one by one they straggled in at last and took shelter under
+the tent, cold, scared, and streaming with water; but to have company
+in misery seemed something to be grateful for. They could not talk, the
+old sail flapped so furiously, even if the other noises would have
+allowed them. The tempest rose higher and higher, and presently the
+sail tore loose from its fastenings and went winging away on the blast.
+The boys seized each others' hands and fled, with many tumblings and
+bruises, to the shelter of a great oak that stood upon the river-bank.
+Now the battle was at its highest. Under the ceaseless conflagration of
+lightning that flamed in the skies, everything below stood out in
+clean-cut and shadowless distinctness: the bending trees, the billowy
+river, white with foam, the driving spray of spume-flakes, the dim
+outlines of the high bluffs on the other side, glimpsed through the
+drifting cloud-rack and the slanting veil of rain. Every little while
+some giant tree yielded the fight and fell crashing through the younger
+growth; and the unflagging thunder-peals came now in ear-splitting
+explosive bursts, keen and sharp, and unspeakably appalling. The storm
+culminated in one matchless effort that seemed likely to tear the island
+to pieces, burn it up, drown it to the tree-tops, blow it away, and
+deafen every creature in it, all at one and the same moment. It was a
+wild night for homeless young heads to be out in.
+
+But at last the battle was done, and the forces retired with weaker
+and weaker threatenings and grumblings, and peace resumed her sway. The
+boys went back to camp, a good deal awed; but they found there was
+still something to be thankful for, because the great sycamore, the
+shelter of their beds, was a ruin, now, blasted by the lightnings, and
+they were not under it when the catastrophe happened.
+
+Everything in camp was drenched, the camp-fire as well; for they were
+but heedless lads, like their generation, and had made no provision
+against rain. Here was matter for dismay, for they were soaked through
+and chilled. They were eloquent in their distress; but they presently
+discovered that the fire had eaten so far up under the great log it had
+been built against (where it curved upward and separated itself from
+the ground), that a handbreadth or so of it had escaped wetting; so
+they patiently wrought until, with shreds and bark gathered from the
+under sides of sheltered logs, they coaxed the fire to burn again. Then
+they piled on great dead boughs till they had a roaring furnace, and
+were glad-hearted once more. They dried their boiled ham and had a
+feast, and after that they sat by the fire and expanded and glorified
+their midnight adventure until morning, for there was not a dry spot to
+sleep on, anywhere around.
+
+As the sun began to steal in upon the boys, drowsiness came over them,
+and they went out on the sandbar and lay down to sleep. They got
+scorched out by and by, and drearily set about getting breakfast. After
+the meal they felt rusty, and stiff-jointed, and a little homesick once
+more. Tom saw the signs, and fell to cheering up the pirates as well as
+he could. But they cared nothing for marbles, or circus, or swimming,
+or anything. He reminded them of the imposing secret, and raised a ray
+of cheer. While it lasted, he got them interested in a new device. This
+was to knock off being pirates, for a while, and be Indians for a
+change. They were attracted by this idea; so it was not long before
+they were stripped, and striped from head to heel with black mud, like
+so many zebras--all of them chiefs, of course--and then they went
+tearing through the woods to attack an English settlement.
+
+By and by they separated into three hostile tribes, and darted upon
+each other from ambush with dreadful war-whoops, and killed and scalped
+each other by thousands. It was a gory day. Consequently it was an
+extremely satisfactory one.
+
+They assembled in camp toward supper-time, hungry and happy; but now a
+difficulty arose--hostile Indians could not break the bread of
+hospitality together without first making peace, and this was a simple
+impossibility without smoking a pipe of peace. There was no other
+process that ever they had heard of. Two of the savages almost wished
+they had remained pirates. However, there was no other way; so with
+such show of cheerfulness as they could muster they called for the pipe
+and took their whiff as it passed, in due form.
+
+And behold, they were glad they had gone into savagery, for they had
+gained something; they found that they could now smoke a little without
+having to go and hunt for a lost knife; they did not get sick enough to
+be seriously uncomfortable. They were not likely to fool away this high
+promise for lack of effort. No, they practised cautiously, after
+supper, with right fair success, and so they spent a jubilant evening.
+They were prouder and happier in their new acquirement than they would
+have been in the scalping and skinning of the Six Nations. We will
+leave them to smoke and chatter and brag, since we have no further use
+for them at present.
+
+
+
+CHAPTER XVII
+
+BUT there was no hilarity in the little town that same tranquil
+Saturday afternoon. The Harpers, and Aunt Polly's family, were being
+put into mourning, with great grief and many tears. An unusual quiet
+possessed the village, although it was ordinarily quiet enough, in all
+conscience. The villagers conducted their concerns with an absent air,
+and talked little; but they sighed often. The Saturday holiday seemed a
+burden to the children. They had no heart in their sports, and
+gradually gave them up.
+
+In the afternoon Becky Thatcher found herself moping about the
+deserted schoolhouse yard, and feeling very melancholy. But she found
+nothing there to comfort her. She soliloquized:
+
+"Oh, if I only had a brass andiron-knob again! But I haven't got
+anything now to remember him by." And she choked back a little sob.
+
+Presently she stopped, and said to herself:
+
+"It was right here. Oh, if it was to do over again, I wouldn't say
+that--I wouldn't say it for the whole world. But he's gone now; I'll
+never, never, never see him any more."
+
+This thought broke her down, and she wandered away, with tears rolling
+down her cheeks. Then quite a group of boys and girls--playmates of
+Tom's and Joe's--came by, and stood looking over the paling fence and
+talking in reverent tones of how Tom did so-and-so the last time they
+saw him, and how Joe said this and that small trifle (pregnant with
+awful prophecy, as they could easily see now!)--and each speaker
+pointed out the exact spot where the lost lads stood at the time, and
+then added something like "and I was a-standing just so--just as I am
+now, and as if you was him--I was as close as that--and he smiled, just
+this way--and then something seemed to go all over me, like--awful, you
+know--and I never thought what it meant, of course, but I can see now!"
+
+Then there was a dispute about who saw the dead boys last in life, and
+many claimed that dismal distinction, and offered evidences, more or
+less tampered with by the witness; and when it was ultimately decided
+who DID see the departed last, and exchanged the last words with them,
+the lucky parties took upon themselves a sort of sacred importance, and
+were gaped at and envied by all the rest. One poor chap, who had no
+other grandeur to offer, said with tolerably manifest pride in the
+remembrance:
+
+"Well, Tom Sawyer he licked me once."
+
+But that bid for glory was a failure. Most of the boys could say that,
+and so that cheapened the distinction too much. The group loitered
+away, still recalling memories of the lost heroes, in awed voices.
+
+When the Sunday-school hour was finished, the next morning, the bell
+began to toll, instead of ringing in the usual way. It was a very still
+Sabbath, and the mournful sound seemed in keeping with the musing hush
+that lay upon nature. The villagers began to gather, loitering a moment
+in the vestibule to converse in whispers about the sad event. But there
+was no whispering in the house; only the funereal rustling of dresses
+as the women gathered to their seats disturbed the silence there. None
+could remember when the little church had been so full before. There
+was finally a waiting pause, an expectant dumbness, and then Aunt Polly
+entered, followed by Sid and Mary, and they by the Harper family, all
+in deep black, and the whole congregation, the old minister as well,
+rose reverently and stood until the mourners were seated in the front
+pew. There was another communing silence, broken at intervals by
+muffled sobs, and then the minister spread his hands abroad and prayed.
+A moving hymn was sung, and the text followed: "I am the Resurrection
+and the Life."
+
+As the service proceeded, the clergyman drew such pictures of the
+graces, the winning ways, and the rare promise of the lost lads that
+every soul there, thinking he recognized these pictures, felt a pang in
+remembering that he had persistently blinded himself to them always
+before, and had as persistently seen only faults and flaws in the poor
+boys. The minister related many a touching incident in the lives of the
+departed, too, which illustrated their sweet, generous natures, and the
+people could easily see, now, how noble and beautiful those episodes
+were, and remembered with grief that at the time they occurred they had
+seemed rank rascalities, well deserving of the cowhide. The
+congregation became more and more moved, as the pathetic tale went on,
+till at last the whole company broke down and joined the weeping
+mourners in a chorus of anguished sobs, the preacher himself giving way
+to his feelings, and crying in the pulpit.
+
+There was a rustle in the gallery, which nobody noticed; a moment
+later the church door creaked; the minister raised his streaming eyes
+above his handkerchief, and stood transfixed! First one and then
+another pair of eyes followed the minister's, and then almost with one
+impulse the congregation rose and stared while the three dead boys came
+marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
+drooping rags, sneaking sheepishly in the rear! They had been hid in
+the unused gallery listening to their own funeral sermon!
+
+Aunt Polly, Mary, and the Harpers threw themselves upon their restored
+ones, smothered them with kisses and poured out thanksgivings, while
+poor Huck stood abashed and uncomfortable, not knowing exactly what to
+do or where to hide from so many unwelcoming eyes. He wavered, and
+started to slink away, but Tom seized him and said:
+
+"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
+
+"And so they shall. I'm glad to see him, poor motherless thing!" And
+the loving attentions Aunt Polly lavished upon him were the one thing
+capable of making him more uncomfortable than he was before.
+
+Suddenly the minister shouted at the top of his voice: "Praise God
+from whom all blessings flow--SING!--and put your hearts in it!"
+
+And they did. Old Hundred swelled up with a triumphant burst, and
+while it shook the rafters Tom Sawyer the Pirate looked around upon the
+envying juveniles about him and confessed in his heart that this was
+the proudest moment of his life.
+
+As the "sold" congregation trooped out they said they would almost be
+willing to be made ridiculous again to hear Old Hundred sung like that
+once more.
+
+Tom got more cuffs and kisses that day--according to Aunt Polly's
+varying moods--than he had earned before in a year; and he hardly knew
+which expressed the most gratefulness to God and affection for himself.
+
+
+
+CHAPTER XVIII
+
+THAT was Tom's great secret--the scheme to return home with his
+brother pirates and attend their own funerals. They had paddled over to
+the Missouri shore on a log, at dusk on Saturday, landing five or six
+miles below the village; they had slept in the woods at the edge of the
+town till nearly daylight, and had then crept through back lanes and
+alleys and finished their sleep in the gallery of the church among a
+chaos of invalided benches.
+
+At breakfast, Monday morning, Aunt Polly and Mary were very loving to
+Tom, and very attentive to his wants. There was an unusual amount of
+talk. In the course of it Aunt Polly said:
+
+"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
+suffering 'most a week so you boys had a good time, but it is a pity
+you could be so hard-hearted as to let me suffer so. If you could come
+over on a log to go to your funeral, you could have come over and give
+me a hint some way that you warn't dead, but only run off."
+
+"Yes, you could have done that, Tom," said Mary; "and I believe you
+would if you had thought of it."
+
+"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
+now, would you, if you'd thought of it?"
+
+"I--well, I don't know. 'Twould 'a' spoiled everything."
+
+"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
+tone that discomforted the boy. "It would have been something if you'd
+cared enough to THINK of it, even if you didn't DO it."
+
+"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
+giddy way--he is always in such a rush that he never thinks of
+anything."
+
+"More's the pity. Sid would have thought. And Sid would have come and
+DONE it, too. Tom, you'll look back, some day, when it's too late, and
+wish you'd cared a little more for me when it would have cost you so
+little."
+
+"Now, auntie, you know I do care for you," said Tom.
+
+"I'd know it better if you acted more like it."
+
+"I wish now I'd thought," said Tom, with a repentant tone; "but I
+dreamt about you, anyway. That's something, ain't it?"
+
+"It ain't much--a cat does that much--but it's better than nothing.
+What did you dream?"
+
+"Why, Wednesday night I dreamt that you was sitting over there by the
+bed, and Sid was sitting by the woodbox, and Mary next to him."
+
+"Well, so we did. So we always do. I'm glad your dreams could take
+even that much trouble about us."
+
+"And I dreamt that Joe Harper's mother was here."
+
+"Why, she was here! Did you dream any more?"
+
+"Oh, lots. But it's so dim, now."
+
+"Well, try to recollect--can't you?"
+
+"Somehow it seems to me that the wind--the wind blowed the--the--"
+
+"Try harder, Tom! The wind did blow something. Come!"
+
+Tom pressed his fingers on his forehead an anxious minute, and then
+said:
+
+"I've got it now! I've got it now! It blowed the candle!"
+
+"Mercy on us! Go on, Tom--go on!"
+
+"And it seems to me that you said, 'Why, I believe that that door--'"
+
+"Go ON, Tom!"
+
+"Just let me study a moment--just a moment. Oh, yes--you said you
+believed the door was open."
+
+"As I'm sitting here, I did! Didn't I, Mary! Go on!"
+
+"And then--and then--well I won't be certain, but it seems like as if
+you made Sid go and--and--"
+
+"Well? Well? What did I make him do, Tom? What did I make him do?"
+
+"You made him--you--Oh, you made him shut it."
+
+"Well, for the land's sake! I never heard the beat of that in all my
+days! Don't tell ME there ain't anything in dreams, any more. Sereny
+Harper shall know of this before I'm an hour older. I'd like to see her
+get around THIS with her rubbage 'bout superstition. Go on, Tom!"
+
+"Oh, it's all getting just as bright as day, now. Next you said I
+warn't BAD, only mischeevous and harum-scarum, and not any more
+responsible than--than--I think it was a colt, or something."
+
+"And so it was! Well, goodness gracious! Go on, Tom!"
+
+"And then you began to cry."
+
+"So I did. So I did. Not the first time, neither. And then--"
+
+"Then Mrs. Harper she began to cry, and said Joe was just the same,
+and she wished she hadn't whipped him for taking cream when she'd
+throwed it out her own self--"
+
+"Tom! The sperrit was upon you! You was a prophesying--that's what you
+was doing! Land alive, go on, Tom!"
+
+"Then Sid he said--he said--"
+
+"I don't think I said anything," said Sid.
+
+"Yes you did, Sid," said Mary.
+
+"Shut your heads and let Tom go on! What did he say, Tom?"
+
+"He said--I THINK he said he hoped I was better off where I was gone
+to, but if I'd been better sometimes--"
+
+"THERE, d'you hear that! It was his very words!"
+
+"And you shut him up sharp."
+
+"I lay I did! There must 'a' been an angel there. There WAS an angel
+there, somewheres!"
+
+"And Mrs. Harper told about Joe scaring her with a firecracker, and
+you told about Peter and the Painkiller--"
+
+"Just as true as I live!"
+
+"And then there was a whole lot of talk 'bout dragging the river for
+us, and 'bout having the funeral Sunday, and then you and old Miss
+Harper hugged and cried, and she went."
+
+"It happened just so! It happened just so, as sure as I'm a-sitting in
+these very tracks. Tom, you couldn't told it more like if you'd 'a'
+seen it! And then what? Go on, Tom!"
+
+"Then I thought you prayed for me--and I could see you and hear every
+word you said. And you went to bed, and I was so sorry that I took and
+wrote on a piece of sycamore bark, 'We ain't dead--we are only off
+being pirates,' and put it on the table by the candle; and then you
+looked so good, laying there asleep, that I thought I went and leaned
+over and kissed you on the lips."
+
+"Did you, Tom, DID you! I just forgive you everything for that!" And
+she seized the boy in a crushing embrace that made him feel like the
+guiltiest of villains.
+
+"It was very kind, even though it was only a--dream," Sid soliloquized
+just audibly.
+
+"Shut up, Sid! A body does just the same in a dream as he'd do if he
+was awake. Here's a big Milum apple I've been saving for you, Tom, if
+you was ever found again--now go 'long to school. I'm thankful to the
+good God and Father of us all I've got you back, that's long-suffering
+and merciful to them that believe on Him and keep His word, though
+goodness knows I'm unworthy of it, but if only the worthy ones got His
+blessings and had His hand to help them over the rough places, there's
+few enough would smile here or ever enter into His rest when the long
+night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
+hendered me long enough."
+
+The children left for school, and the old lady to call on Mrs. Harper
+and vanquish her realism with Tom's marvellous dream. Sid had better
+judgment than to utter the thought that was in his mind as he left the
+house. It was this: "Pretty thin--as long a dream as that, without any
+mistakes in it!"
+
+What a hero Tom was become, now! He did not go skipping and prancing,
+but moved with a dignified swagger as became a pirate who felt that the
+public eye was on him. And indeed it was; he tried not to seem to see
+the looks or hear the remarks as he passed along, but they were food
+and drink to him. Smaller boys than himself flocked at his heels, as
+proud to be seen with him, and tolerated by him, as if he had been the
+drummer at the head of a procession or the elephant leading a menagerie
+into town. Boys of his own size pretended not to know he had been away
+at all; but they were consuming with envy, nevertheless. They would
+have given anything to have that swarthy suntanned skin of his, and his
+glittering notoriety; and Tom would not have parted with either for a
+circus.
+
+At school the children made so much of him and of Joe, and delivered
+such eloquent admiration from their eyes, that the two heroes were not
+long in becoming insufferably "stuck-up." They began to tell their
+adventures to hungry listeners--but they only began; it was not a thing
+likely to have an end, with imaginations like theirs to furnish
+material. And finally, when they got out their pipes and went serenely
+puffing around, the very summit of glory was reached.
+
+Tom decided that he could be independent of Becky Thatcher now. Glory
+was sufficient. He would live for glory. Now that he was distinguished,
+maybe she would be wanting to "make up." Well, let her--she should see
+that he could be as indifferent as some other people. Presently she
+arrived. Tom pretended not to see her. He moved away and joined a group
+of boys and girls and began to talk. Soon he observed that she was
+tripping gayly back and forth with flushed face and dancing eyes,
+pretending to be busy chasing schoolmates, and screaming with laughter
+when she made a capture; but he noticed that she always made her
+captures in his vicinity, and that she seemed to cast a conscious eye
+in his direction at such times, too. It gratified all the vicious
+vanity that was in him; and so, instead of winning him, it only "set
+him up" the more and made him the more diligent to avoid betraying that
+he knew she was about. Presently she gave over skylarking, and moved
+irresolutely about, sighing once or twice and glancing furtively and
+wistfully toward Tom. Then she observed that now Tom was talking more
+particularly to Amy Lawrence than to any one else. She felt a sharp
+pang and grew disturbed and uneasy at once. She tried to go away, but
+her feet were treacherous, and carried her to the group instead. She
+said to a girl almost at Tom's elbow--with sham vivacity:
+
+"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
+
+"I did come--didn't you see me?"
+
+"Why, no! Did you? Where did you sit?"
+
+"I was in Miss Peters' class, where I always go. I saw YOU."
+
+"Did you? Why, it's funny I didn't see you. I wanted to tell you about
+the picnic."
+
+"Oh, that's jolly. Who's going to give it?"
+
+"My ma's going to let me have one."
+
+"Oh, goody; I hope she'll let ME come."
+
+"Well, she will. The picnic's for me. She'll let anybody come that I
+want, and I want you."
+
+"That's ever so nice. When is it going to be?"
+
+"By and by. Maybe about vacation."
+
+"Oh, won't it be fun! You going to have all the girls and boys?"
+
+"Yes, every one that's friends to me--or wants to be"; and she glanced
+ever so furtively at Tom, but he talked right along to Amy Lawrence
+about the terrible storm on the island, and how the lightning tore the
+great sycamore tree "all to flinders" while he was "standing within
+three feet of it."
+
+"Oh, may I come?" said Grace Miller.
+
+"Yes."
+
+"And me?" said Sally Rogers.
+
+"Yes."
+
+"And me, too?" said Susy Harper. "And Joe?"
+
+"Yes."
+
+And so on, with clapping of joyful hands till all the group had begged
+for invitations but Tom and Amy. Then Tom turned coolly away, still
+talking, and took Amy with him. Becky's lips trembled and the tears
+came to her eyes; she hid these signs with a forced gayety and went on
+chattering, but the life had gone out of the picnic, now, and out of
+everything else; she got away as soon as she could and hid herself and
+had what her sex call "a good cry." Then she sat moody, with wounded
+pride, till the bell rang. She roused up, now, with a vindictive cast
+in her eye, and gave her plaited tails a shake and said she knew what
+SHE'D do.
+
+At recess Tom continued his flirtation with Amy with jubilant
+self-satisfaction. And he kept drifting about to find Becky and lacerate
+her with the performance. At last he spied her, but there was a sudden
+falling of his mercury. She was sitting cosily on a little bench behind
+the schoolhouse looking at a picture-book with Alfred Temple--and so
+absorbed were they, and their heads so close together over the book,
+that they did not seem to be conscious of anything in the world besides.
+Jealousy ran red-hot through Tom's veins. He began to hate himself for
+throwing away the chance Becky had offered for a reconciliation. He
+called himself a fool, and all the hard names he could think of. He
+wanted to cry with vexation. Amy chatted happily along, as they walked,
+for her heart was singing, but Tom's tongue had lost its function. He
+did not hear what Amy was saying, and whenever she paused expectantly he
+could only stammer an awkward assent, which was as often misplaced as
+otherwise. He kept drifting to the rear of the schoolhouse, again and
+again, to sear his eyeballs with the hateful spectacle there. He could
+not help it. And it maddened him to see, as he thought he saw, that
+Becky Thatcher never once suspected that he was even in the land of the
+living. But she did see, nevertheless; and she knew she was winning her
+fight, too, and was glad to see him suffer as she had suffered.
+
+Amy's happy prattle became intolerable. Tom hinted at things he had to
+attend to; things that must be done; and time was fleeting. But in
+vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
+going to get rid of her?" At last he must be attending to those
+things--and she said artlessly that she would be "around" when school
+let out. And he hastened away, hating her for it.
+
+"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
+town but that Saint Louis smarty that thinks he dresses so fine and is
+aristocracy! Oh, all right, I licked you the first day you ever saw
+this town, mister, and I'll lick you again! You just wait till I catch
+you out! I'll just take and--"
+
+And he went through the motions of thrashing an imaginary boy
+--pummelling the air, and kicking and gouging. "Oh, you do, do you? You
+holler 'nough, do you? Now, then, let that learn you!" And so the
+imaginary flogging was finished to his satisfaction.
+
+Tom fled home at noon. His conscience could not endure any more of
+Amy's grateful happiness, and his jealousy could bear no more of the
+other distress. Becky resumed her picture inspections with Alfred, but
+as the minutes dragged along and no Tom came to suffer, her triumph
+began to cloud and she lost interest; gravity and absent-mindedness
+followed, and then melancholy; two or three times she pricked up her
+ear at a footstep, but it was a false hope; no Tom came. At last she
+grew entirely miserable and wished she hadn't carried it so far. When
+poor Alfred, seeing that he was losing her, he did not know how, kept
+exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
+at last, and said, "Oh, don't bother me! I don't care for them!" and
+burst into tears, and got up and walked away.
+
+Alfred dropped alongside and was going to try to comfort her, but she
+said:
+
+"Go away and leave me alone, can't you! I hate you!"
+
+So the boy halted, wondering what he could have done--for she had said
+she would look at pictures all through the nooning--and she walked on,
+crying. Then Alfred went musing into the deserted schoolhouse. He was
+humiliated and angry. He easily guessed his way to the truth--the girl
+had simply made a convenience of him to vent her spite upon Tom Sawyer.
+He was far from hating Tom the less when this thought occurred to him.
+He wished there was some way to get that boy into trouble without much
+risk to himself. Tom's spelling-book fell under his eye. Here was his
+opportunity. He gratefully opened to the lesson for the afternoon and
+poured ink upon the page.
+
+Becky, glancing in at a window behind him at the moment, saw the act,
+and moved on, without discovering herself. She started homeward, now,
+intending to find Tom and tell him; Tom would be thankful and their
+troubles would be healed. Before she was half way home, however, she
+had changed her mind. The thought of Tom's treatment of her when she
+was talking about her picnic came scorching back and filled her with
+shame. She resolved to let him get whipped on the damaged
+spelling-book's account, and to hate him forever, into the bargain.
+
+
+
+CHAPTER XIX
+
+TOM arrived at home in a dreary mood, and the first thing his aunt
+said to him showed him that he had brought his sorrows to an
+unpromising market:
+
+"Tom, I've a notion to skin you alive!"
+
+"Auntie, what have I done?"
+
+"Well, you've done enough. Here I go over to Sereny Harper, like an
+old softy, expecting I'm going to make her believe all that rubbage
+about that dream, when lo and behold you she'd found out from Joe that
+you was over here and heard all the talk we had that night. Tom, I
+don't know what is to become of a boy that will act like that. It makes
+me feel so bad to think you could let me go to Sereny Harper and make
+such a fool of myself and never say a word."
+
+This was a new aspect of the thing. His smartness of the morning had
+seemed to Tom a good joke before, and very ingenious. It merely looked
+mean and shabby now. He hung his head and could not think of anything
+to say for a moment. Then he said:
+
+"Auntie, I wish I hadn't done it--but I didn't think."
+
+"Oh, child, you never think. You never think of anything but your own
+selfishness. You could think to come all the way over here from
+Jackson's Island in the night to laugh at our troubles, and you could
+think to fool me with a lie about a dream; but you couldn't ever think
+to pity us and save us from sorrow."
+
+"Auntie, I know now it was mean, but I didn't mean to be mean. I
+didn't, honest. And besides, I didn't come over here to laugh at you
+that night."
+
+"What did you come for, then?"
+
+"It was to tell you not to be uneasy about us, because we hadn't got
+drownded."
+
+"Tom, Tom, I would be the thankfullest soul in this world if I could
+believe you ever had as good a thought as that, but you know you never
+did--and I know it, Tom."
+
+"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
+
+"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
+worse."
+
+"It ain't a lie, auntie; it's the truth. I wanted to keep you from
+grieving--that was all that made me come."
+
+"I'd give the whole world to believe that--it would cover up a power
+of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
+ain't reasonable; because, why didn't you tell me, child?"
+
+"Why, you see, when you got to talking about the funeral, I just got
+all full of the idea of our coming and hiding in the church, and I
+couldn't somehow bear to spoil it. So I just put the bark back in my
+pocket and kept mum."
+
+"What bark?"
+
+"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
+you'd waked up when I kissed you--I do, honest."
+
+The hard lines in his aunt's face relaxed and a sudden tenderness
+dawned in her eyes.
+
+"DID you kiss me, Tom?"
+
+"Why, yes, I did."
+
+"Are you sure you did, Tom?"
+
+"Why, yes, I did, auntie--certain sure."
+
+"What did you kiss me for, Tom?"
+
+"Because I loved you so, and you laid there moaning and I was so sorry."
+
+The words sounded like truth. The old lady could not hide a tremor in
+her voice when she said:
+
+"Kiss me again, Tom!--and be off with you to school, now, and don't
+bother me any more."
+
+The moment he was gone, she ran to a closet and got out the ruin of a
+jacket which Tom had gone pirating in. Then she stopped, with it in her
+hand, and said to herself:
+
+"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
+blessed, blessed lie, there's such a comfort come from it. I hope the
+Lord--I KNOW the Lord will forgive him, because it was such
+goodheartedness in him to tell it. But I don't want to find out it's a
+lie. I won't look."
+
+She put the jacket away, and stood by musing a minute. Twice she put
+out her hand to take the garment again, and twice she refrained. Once
+more she ventured, and this time she fortified herself with the
+thought: "It's a good lie--it's a good lie--I won't let it grieve me."
+So she sought the jacket pocket. A moment later she was reading Tom's
+piece of bark through flowing tears and saying: "I could forgive the
+boy, now, if he'd committed a million sins!"
+
+
+
+CHAPTER XX
+
+THERE was something about Aunt Polly's manner, when she kissed Tom,
+that swept away his low spirits and made him lighthearted and happy
+again. He started to school and had the luck of coming upon Becky
+Thatcher at the head of Meadow Lane. His mood always determined his
+manner. Without a moment's hesitation he ran to her and said:
+
+"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
+ever do that way again, as long as ever I live--please make up, won't
+you?"
+
+The girl stopped and looked him scornfully in the face:
+
+"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
+never speak to you again."
+
+She tossed her head and passed on. Tom was so stunned that he had not
+even presence of mind enough to say "Who cares, Miss Smarty?" until the
+right time to say it had gone by. So he said nothing. But he was in a
+fine rage, nevertheless. He moped into the schoolyard wishing she were
+a boy, and imagining how he would trounce her if she were. He presently
+encountered her and delivered a stinging remark as he passed. She
+hurled one in return, and the angry breach was complete. It seemed to
+Becky, in her hot resentment, that she could hardly wait for school to
+"take in," she was so impatient to see Tom flogged for the injured
+spelling-book. If she had had any lingering notion of exposing Alfred
+Temple, Tom's offensive fling had driven it entirely away.
+
+Poor girl, she did not know how fast she was nearing trouble herself.
+The master, Mr. Dobbins, had reached middle age with an unsatisfied
+ambition. The darling of his desires was, to be a doctor, but poverty
+had decreed that he should be nothing higher than a village
+schoolmaster. Every day he took a mysterious book out of his desk and
+absorbed himself in it at times when no classes were reciting. He kept
+that book under lock and key. There was not an urchin in school but was
+perishing to have a glimpse of it, but the chance never came. Every boy
+and girl had a theory about the nature of that book; but no two
+theories were alike, and there was no way of getting at the facts in
+the case. Now, as Becky was passing by the desk, which stood near the
+door, she noticed that the key was in the lock! It was a precious
+moment. She glanced around; found herself alone, and the next instant
+she had the book in her hands. The title-page--Professor Somebody's
+ANATOMY--carried no information to her mind; so she began to turn the
+leaves. She came at once upon a handsomely engraved and colored
+frontispiece--a human figure, stark naked. At that moment a shadow fell
+on the page and Tom Sawyer stepped in at the door and caught a glimpse
+of the picture. Becky snatched at the book to close it, and had the
+hard luck to tear the pictured page half down the middle. She thrust
+the volume into the desk, turned the key, and burst out crying with
+shame and vexation.
+
+"Tom Sawyer, you are just as mean as you can be, to sneak up on a
+person and look at what they're looking at."
+
+"How could I know you was looking at anything?"
+
+"You ought to be ashamed of yourself, Tom Sawyer; you know you're
+going to tell on me, and oh, what shall I do, what shall I do! I'll be
+whipped, and I never was whipped in school."
+
+Then she stamped her little foot and said:
+
+"BE so mean if you want to! I know something that's going to happen.
+You just wait and you'll see! Hateful, hateful, hateful!"--and she
+flung out of the house with a new explosion of crying.
+
+Tom stood still, rather flustered by this onslaught. Presently he said
+to himself:
+
+"What a curious kind of a fool a girl is! Never been licked in school!
+Shucks! What's a licking! That's just like a girl--they're so
+thin-skinned and chicken-hearted. Well, of course I ain't going to tell
+old Dobbins on this little fool, because there's other ways of getting
+even on her, that ain't so mean; but what of it? Old Dobbins will ask
+who it was tore his book. Nobody'll answer. Then he'll do just the way
+he always does--ask first one and then t'other, and when he comes to the
+right girl he'll know it, without any telling. Girls' faces always tell
+on them. They ain't got any backbone. She'll get licked. Well, it's a
+kind of a tight place for Becky Thatcher, because there ain't any way
+out of it." Tom conned the thing a moment longer, and then added: "All
+right, though; she'd like to see me in just such a fix--let her sweat it
+out!"
+
+Tom joined the mob of skylarking scholars outside. In a few moments
+the master arrived and school "took in." Tom did not feel a strong
+interest in his studies. Every time he stole a glance at the girls'
+side of the room Becky's face troubled him. Considering all things, he
+did not want to pity her, and yet it was all he could do to help it. He
+could get up no exultation that was really worthy the name. Presently
+the spelling-book discovery was made, and Tom's mind was entirely full
+of his own matters for a while after that. Becky roused up from her
+lethargy of distress and showed good interest in the proceedings. She
+did not expect that Tom could get out of his trouble by denying that he
+spilt the ink on the book himself; and she was right. The denial only
+seemed to make the thing worse for Tom. Becky supposed she would be
+glad of that, and she tried to believe she was glad of it, but she
+found she was not certain. When the worst came to the worst, she had an
+impulse to get up and tell on Alfred Temple, but she made an effort and
+forced herself to keep still--because, said she to herself, "he'll tell
+about me tearing the picture sure. I wouldn't say a word, not to save
+his life!"
+
+Tom took his whipping and went back to his seat not at all
+broken-hearted, for he thought it was possible that he had unknowingly
+upset the ink on the spelling-book himself, in some skylarking bout--he
+had denied it for form's sake and because it was custom, and had stuck
+to the denial from principle.
+
+A whole hour drifted by, the master sat nodding in his throne, the air
+was drowsy with the hum of study. By and by, Mr. Dobbins straightened
+himself up, yawned, then unlocked his desk, and reached for his book,
+but seemed undecided whether to take it out or leave it. Most of the
+pupils glanced up languidly, but there were two among them that watched
+his movements with intent eyes. Mr. Dobbins fingered his book absently
+for a while, then took it out and settled himself in his chair to read!
+Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
+look as she did, with a gun levelled at its head. Instantly he forgot
+his quarrel with her. Quick--something must be done! done in a flash,
+too! But the very imminence of the emergency paralyzed his invention.
+Good!--he had an inspiration! He would run and snatch the book, spring
+through the door and fly. But his resolution shook for one little
+instant, and the chance was lost--the master opened the volume. If Tom
+only had the wasted opportunity back again! Too late. There was no help
+for Becky now, he said. The next moment the master faced the school.
+Every eye sank under his gaze. There was that in it which smote even
+the innocent with fear. There was silence while one might count ten
+--the master was gathering his wrath. Then he spoke: "Who tore this book?"
+
+There was not a sound. One could have heard a pin drop. The stillness
+continued; the master searched face after face for signs of guilt.
+
+"Benjamin Rogers, did you tear this book?"
+
+A denial. Another pause.
+
+"Joseph Harper, did you?"
+
+Another denial. Tom's uneasiness grew more and more intense under the
+slow torture of these proceedings. The master scanned the ranks of
+boys--considered a while, then turned to the girls:
+
+"Amy Lawrence?"
+
+A shake of the head.
+
+"Gracie Miller?"
+
+The same sign.
+
+"Susan Harper, did you do this?"
+
+Another negative. The next girl was Becky Thatcher. Tom was trembling
+from head to foot with excitement and a sense of the hopelessness of
+the situation.
+
+"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
+--"did you tear--no, look me in the face" [her hands rose in appeal]
+--"did you tear this book?"
+
+A thought shot like lightning through Tom's brain. He sprang to his
+feet and shouted--"I done it!"
+
+The school stared in perplexity at this incredible folly. Tom stood a
+moment, to gather his dismembered faculties; and when he stepped
+forward to go to his punishment the surprise, the gratitude, the
+adoration that shone upon him out of poor Becky's eyes seemed pay
+enough for a hundred floggings. Inspired by the splendor of his own
+act, he took without an outcry the most merciless flaying that even Mr.
+Dobbins had ever administered; and also received with indifference the
+added cruelty of a command to remain two hours after school should be
+dismissed--for he knew who would wait for him outside till his
+captivity was done, and not count the tedious time as loss, either.
+
+Tom went to bed that night planning vengeance against Alfred Temple;
+for with shame and repentance Becky had told him all, not forgetting
+her own treachery; but even the longing for vengeance had to give way,
+soon, to pleasanter musings, and he fell asleep at last with Becky's
+latest words lingering dreamily in his ear--
+
+"Tom, how COULD you be so noble!"
+
+
+
+CHAPTER XXI
+
+VACATION was approaching. The schoolmaster, always severe, grew
+severer and more exacting than ever, for he wanted the school to make a
+good showing on "Examination" day. His rod and his ferule were seldom
+idle now--at least among the smaller pupils. Only the biggest boys, and
+young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
+lashings were very vigorous ones, too; for although he carried, under
+his wig, a perfectly bald and shiny head, he had only reached middle
+age, and there was no sign of feebleness in his muscle. As the great
+day approached, all the tyranny that was in him came to the surface; he
+seemed to take a vindictive pleasure in punishing the least
+shortcomings. The consequence was, that the smaller boys spent their
+days in terror and suffering and their nights in plotting revenge. They
+threw away no opportunity to do the master a mischief. But he kept
+ahead all the time. The retribution that followed every vengeful
+success was so sweeping and majestic that the boys always retired from
+the field badly worsted. At last they conspired together and hit upon a
+plan that promised a dazzling victory. They swore in the sign-painter's
+boy, told him the scheme, and asked his help. He had his own reasons
+for being delighted, for the master boarded in his father's family and
+had given the boy ample cause to hate him. The master's wife would go
+on a visit to the country in a few days, and there would be nothing to
+interfere with the plan; the master always prepared himself for great
+occasions by getting pretty well fuddled, and the sign-painter's boy
+said that when the dominie had reached the proper condition on
+Examination Evening he would "manage the thing" while he napped in his
+chair; then he would have him awakened at the right time and hurried
+away to school.
+
+In the fulness of time the interesting occasion arrived. At eight in
+the evening the schoolhouse was brilliantly lighted, and adorned with
+wreaths and festoons of foliage and flowers. The master sat throned in
+his great chair upon a raised platform, with his blackboard behind him.
+He was looking tolerably mellow. Three rows of benches on each side and
+six rows in front of him were occupied by the dignitaries of the town
+and by the parents of the pupils. To his left, back of the rows of
+citizens, was a spacious temporary platform upon which were seated the
+scholars who were to take part in the exercises of the evening; rows of
+small boys, washed and dressed to an intolerable state of discomfort;
+rows of gawky big boys; snowbanks of girls and young ladies clad in
+lawn and muslin and conspicuously conscious of their bare arms, their
+grandmothers' ancient trinkets, their bits of pink and blue ribbon and
+the flowers in their hair. All the rest of the house was filled with
+non-participating scholars.
+
+The exercises began. A very little boy stood up and sheepishly
+recited, "You'd scarce expect one of my age to speak in public on the
+stage," etc.--accompanying himself with the painfully exact and
+spasmodic gestures which a machine might have used--supposing the
+machine to be a trifle out of order. But he got through safely, though
+cruelly scared, and got a fine round of applause when he made his
+manufactured bow and retired.
+
+A little shamefaced girl lisped, "Mary had a little lamb," etc.,
+performed a compassion-inspiring curtsy, got her meed of applause, and
+sat down flushed and happy.
+
+Tom Sawyer stepped forward with conceited confidence and soared into
+the unquenchable and indestructible "Give me liberty or give me death"
+speech, with fine fury and frantic gesticulation, and broke down in the
+middle of it. A ghastly stage-fright seized him, his legs quaked under
+him and he was like to choke. True, he had the manifest sympathy of the
+house but he had the house's silence, too, which was even worse than
+its sympathy. The master frowned, and this completed the disaster. Tom
+struggled awhile and then retired, utterly defeated. There was a weak
+attempt at applause, but it died early.
+
+"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
+Down," and other declamatory gems. Then there were reading exercises,
+and a spelling fight. The meagre Latin class recited with honor. The
+prime feature of the evening was in order, now--original "compositions"
+by the young ladies. Each in her turn stepped forward to the edge of
+the platform, cleared her throat, held up her manuscript (tied with
+dainty ribbon), and proceeded to read, with labored attention to
+"expression" and punctuation. The themes were the same that had been
+illuminated upon similar occasions by their mothers before them, their
+grandmothers, and doubtless all their ancestors in the female line
+clear back to the Crusades. "Friendship" was one; "Memories of Other
+Days"; "Religion in History"; "Dream Land"; "The Advantages of
+Culture"; "Forms of Political Government Compared and Contrasted";
+"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
+
+A prevalent feature in these compositions was a nursed and petted
+melancholy; another was a wasteful and opulent gush of "fine language";
+another was a tendency to lug in by the ears particularly prized words
+and phrases until they were worn entirely out; and a peculiarity that
+conspicuously marked and marred them was the inveterate and intolerable
+sermon that wagged its crippled tail at the end of each and every one
+of them. No matter what the subject might be, a brain-racking effort
+was made to squirm it into some aspect or other that the moral and
+religious mind could contemplate with edification. The glaring
+insincerity of these sermons was not sufficient to compass the
+banishment of the fashion from the schools, and it is not sufficient
+to-day; it never will be sufficient while the world stands, perhaps.
+There is no school in all our land where the young ladies do not feel
+obliged to close their compositions with a sermon; and you will find
+that the sermon of the most frivolous and the least religious girl in
+the school is always the longest and the most relentlessly pious. But
+enough of this. Homely truth is unpalatable.
+
+Let us return to the "Examination." The first composition that was
+read was one entitled "Is this, then, Life?" Perhaps the reader can
+endure an extract from it:
+
+ "In the common walks of life, with what delightful
+ emotions does the youthful mind look forward to some
+ anticipated scene of festivity! Imagination is busy
+ sketching rose-tinted pictures of joy. In fancy, the
+ voluptuous votary of fashion sees herself amid the
+ festive throng, 'the observed of all observers.' Her
+ graceful form, arrayed in snowy robes, is whirling
+ through the mazes of the joyous dance; her eye is
+ brightest, her step is lightest in the gay assembly.
+
+ "In such delicious fancies time quickly glides by,
+ and the welcome hour arrives for her entrance into
+ the Elysian world, of which she has had such bright
+ dreams. How fairy-like does everything appear to
+ her enchanted vision! Each new scene is more charming
+ than the last. But after a while she finds that
+ beneath this goodly exterior, all is vanity, the
+ flattery which once charmed her soul, now grates
+ harshly upon her ear; the ball-room has lost its
+ charms; and with wasted health and imbittered heart,
+ she turns away with the conviction that earthly
+ pleasures cannot satisfy the longings of the soul!"
+
+And so forth and so on. There was a buzz of gratification from time to
+time during the reading, accompanied by whispered ejaculations of "How
+sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
+with a peculiarly afflicting sermon the applause was enthusiastic.
+
+Then arose a slim, melancholy girl, whose face had the "interesting"
+paleness that comes of pills and indigestion, and read a "poem." Two
+stanzas of it will do:
+
+ "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
+
+ "Alabama, good-bye! I love thee well!
+ But yet for a while do I leave thee now!
+ Sad, yes, sad thoughts of thee my heart doth swell,
+ And burning recollections throng my brow!
+ For I have wandered through thy flowery woods;
+ Have roamed and read near Tallapoosa's stream;
+ Have listened to Tallassee's warring floods,
+ And wooed on Coosa's side Aurora's beam.
+
+ "Yet shame I not to bear an o'er-full heart,
+ Nor blush to turn behind my tearful eyes;
+ 'Tis from no stranger land I now must part,
+ 'Tis to no strangers left I yield these sighs.
+ Welcome and home were mine within this State,
+ Whose vales I leave--whose spires fade fast from me
+ And cold must be mine eyes, and heart, and tete,
+ When, dear Alabama! they turn cold on thee!"
+
+There were very few there who knew what "tete" meant, but the poem was
+very satisfactory, nevertheless.
+
+Next appeared a dark-complexioned, black-eyed, black-haired young
+lady, who paused an impressive moment, assumed a tragic expression, and
+began to read in a measured, solemn tone:
+
+ "A VISION
+
+ "Dark and tempestuous was night. Around the
+ throne on high not a single star quivered; but
+ the deep intonations of the heavy thunder
+ constantly vibrated upon the ear; whilst the
+ terrific lightning revelled in angry mood
+ through the cloudy chambers of heaven, seeming
+ to scorn the power exerted over its terror by
+ the illustrious Franklin! Even the boisterous
+ winds unanimously came forth from their mystic
+ homes, and blustered about as if to enhance by
+ their aid the wildness of the scene.
+
+ "At such a time, so dark, so dreary, for human
+ sympathy my very spirit sighed; but instead thereof,
+
+ "'My dearest friend, my counsellor, my comforter
+ and guide--My joy in grief, my second bliss
+ in joy,' came to my side. She moved like one of
+ those bright beings pictured in the sunny walks
+ of fancy's Eden by the romantic and young, a
+ queen of beauty unadorned save by her own
+ transcendent loveliness. So soft was her step, it
+ failed to make even a sound, and but for the
+ magical thrill imparted by her genial touch, as
+ other unobtrusive beauties, she would have glided
+ away un-perceived--unsought. A strange sadness
+ rested upon her features, like icy tears upon
+ the robe of December, as she pointed to the
+ contending elements without, and bade me contemplate
+ the two beings presented."
+
+This nightmare occupied some ten pages of manuscript and wound up with
+a sermon so destructive of all hope to non-Presbyterians that it took
+the first prize. This composition was considered to be the very finest
+effort of the evening. The mayor of the village, in delivering the
+prize to the author of it, made a warm speech in which he said that it
+was by far the most "eloquent" thing he had ever listened to, and that
+Daniel Webster himself might well be proud of it.
+
+It may be remarked, in passing, that the number of compositions in
+which the word "beauteous" was over-fondled, and human experience
+referred to as "life's page," was up to the usual average.
+
+Now the master, mellow almost to the verge of geniality, put his chair
+aside, turned his back to the audience, and began to draw a map of
+America on the blackboard, to exercise the geography class upon. But he
+made a sad business of it with his unsteady hand, and a smothered
+titter rippled over the house. He knew what the matter was, and set
+himself to right it. He sponged out lines and remade them; but he only
+distorted them more than ever, and the tittering was more pronounced.
+He threw his entire attention upon his work, now, as if determined not
+to be put down by the mirth. He felt that all eyes were fastened upon
+him; he imagined he was succeeding, and yet the tittering continued; it
+even manifestly increased. And well it might. There was a garret above,
+pierced with a scuttle over his head; and down through this scuttle
+came a cat, suspended around the haunches by a string; she had a rag
+tied about her head and jaws to keep her from mewing; as she slowly
+descended she curved upward and clawed at the string, she swung
+downward and clawed at the intangible air. The tittering rose higher
+and higher--the cat was within six inches of the absorbed teacher's
+head--down, down, a little lower, and she grabbed his wig with her
+desperate claws, clung to it, and was snatched up into the garret in an
+instant with her trophy still in her possession! And how the light did
+blaze abroad from the master's bald pate--for the sign-painter's boy
+had GILDED it!
+
+That broke up the meeting. The boys were avenged. Vacation had come.
+
+ NOTE:--The pretended "compositions" quoted in
+ this chapter are taken without alteration from a
+ volume entitled "Prose and Poetry, by a Western
+ Lady"--but they are exactly and precisely after
+ the schoolgirl pattern, and hence are much
+ happier than any mere imitations could be.
+
+
+
+CHAPTER XXII
+
+TOM joined the new order of Cadets of Temperance, being attracted by
+the showy character of their "regalia." He promised to abstain from
+smoking, chewing, and profanity as long as he remained a member. Now he
+found out a new thing--namely, that to promise not to do a thing is the
+surest way in the world to make a body want to go and do that very
+thing. Tom soon found himself tormented with a desire to drink and
+swear; the desire grew to be so intense that nothing but the hope of a
+chance to display himself in his red sash kept him from withdrawing
+from the order. Fourth of July was coming; but he soon gave that up
+--gave it up before he had worn his shackles over forty-eight hours--and
+fixed his hopes upon old Judge Frazer, justice of the peace, who was
+apparently on his deathbed and would have a big public funeral, since
+he was so high an official. During three days Tom was deeply concerned
+about the Judge's condition and hungry for news of it. Sometimes his
+hopes ran high--so high that he would venture to get out his regalia
+and practise before the looking-glass. But the Judge had a most
+discouraging way of fluctuating. At last he was pronounced upon the
+mend--and then convalescent. Tom was disgusted; and felt a sense of
+injury, too. He handed in his resignation at once--and that night the
+Judge suffered a relapse and died. Tom resolved that he would never
+trust a man like that again.
+
+The funeral was a fine thing. The Cadets paraded in a style calculated
+to kill the late member with envy. Tom was a free boy again, however
+--there was something in that. He could drink and swear, now--but found
+to his surprise that he did not want to. The simple fact that he could,
+took the desire away, and the charm of it.
+
+Tom presently wondered to find that his coveted vacation was beginning
+to hang a little heavily on his hands.
+
+He attempted a diary--but nothing happened during three days, and so
+he abandoned it.
+
+The first of all the negro minstrel shows came to town, and made a
+sensation. Tom and Joe Harper got up a band of performers and were
+happy for two days.
+
+Even the Glorious Fourth was in some sense a failure, for it rained
+hard, there was no procession in consequence, and the greatest man in
+the world (as Tom supposed), Mr. Benton, an actual United States
+Senator, proved an overwhelming disappointment--for he was not
+twenty-five feet high, nor even anywhere in the neighborhood of it.
+
+A circus came. The boys played circus for three days afterward in
+tents made of rag carpeting--admission, three pins for boys, two for
+girls--and then circusing was abandoned.
+
+A phrenologist and a mesmerizer came--and went again and left the
+village duller and drearier than ever.
+
+There were some boys-and-girls' parties, but they were so few and so
+delightful that they only made the aching voids between ache the harder.
+
+Becky Thatcher was gone to her Constantinople home to stay with her
+parents during vacation--so there was no bright side to life anywhere.
+
+The dreadful secret of the murder was a chronic misery. It was a very
+cancer for permanency and pain.
+
+Then came the measles.
+
+During two long weeks Tom lay a prisoner, dead to the world and its
+happenings. He was very ill, he was interested in nothing. When he got
+upon his feet at last and moved feebly down-town, a melancholy change
+had come over everything and every creature. There had been a
+"revival," and everybody had "got religion," not only the adults, but
+even the boys and girls. Tom went about, hoping against hope for the
+sight of one blessed sinful face, but disappointment crossed him
+everywhere. He found Joe Harper studying a Testament, and turned sadly
+away from the depressing spectacle. He sought Ben Rogers, and found him
+visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
+called his attention to the precious blessing of his late measles as a
+warning. Every boy he encountered added another ton to his depression;
+and when, in desperation, he flew for refuge at last to the bosom of
+Huckleberry Finn and was received with a Scriptural quotation, his
+heart broke and he crept home and to bed realizing that he alone of all
+the town was lost, forever and forever.
+
+And that night there came on a terrific storm, with driving rain,
+awful claps of thunder and blinding sheets of lightning. He covered his
+head with the bedclothes and waited in a horror of suspense for his
+doom; for he had not the shadow of a doubt that all this hubbub was
+about him. He believed he had taxed the forbearance of the powers above
+to the extremity of endurance and that this was the result. It might
+have seemed to him a waste of pomp and ammunition to kill a bug with a
+battery of artillery, but there seemed nothing incongruous about the
+getting up such an expensive thunderstorm as this to knock the turf
+from under an insect like himself.
+
+By and by the tempest spent itself and died without accomplishing its
+object. The boy's first impulse was to be grateful, and reform. His
+second was to wait--for there might not be any more storms.
+
+The next day the doctors were back; Tom had relapsed. The three weeks
+he spent on his back this time seemed an entire age. When he got abroad
+at last he was hardly grateful that he had been spared, remembering how
+lonely was his estate, how companionless and forlorn he was. He drifted
+listlessly down the street and found Jim Hollis acting as judge in a
+juvenile court that was trying a cat for murder, in the presence of her
+victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
+stolen melon. Poor lads! they--like Tom--had suffered a relapse.
+
+
+
+CHAPTER XXIII
+
+AT last the sleepy atmosphere was stirred--and vigorously: the murder
+trial came on in the court. It became the absorbing topic of village
+talk immediately. Tom could not get away from it. Every reference to
+the murder sent a shudder to his heart, for his troubled conscience and
+fears almost persuaded him that these remarks were put forth in his
+hearing as "feelers"; he did not see how he could be suspected of
+knowing anything about the murder, but still he could not be
+comfortable in the midst of this gossip. It kept him in a cold shiver
+all the time. He took Huck to a lonely place to have a talk with him.
+It would be some relief to unseal his tongue for a little while; to
+divide his burden of distress with another sufferer. Moreover, he
+wanted to assure himself that Huck had remained discreet.
+
+"Huck, have you ever told anybody about--that?"
+
+"'Bout what?"
+
+"You know what."
+
+"Oh--'course I haven't."
+
+"Never a word?"
+
+"Never a solitary word, so help me. What makes you ask?"
+
+"Well, I was afeard."
+
+"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
+YOU know that."
+
+Tom felt more comfortable. After a pause:
+
+"Huck, they couldn't anybody get you to tell, could they?"
+
+"Get me to tell? Why, if I wanted that half-breed devil to drownd me
+they could get me to tell. They ain't no different way."
+
+"Well, that's all right, then. I reckon we're safe as long as we keep
+mum. But let's swear again, anyway. It's more surer."
+
+"I'm agreed."
+
+So they swore again with dread solemnities.
+
+"What is the talk around, Huck? I've heard a power of it."
+
+"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
+time. It keeps me in a sweat, constant, so's I want to hide som'ers."
+
+"That's just the same way they go on round me. I reckon he's a goner.
+Don't you feel sorry for him, sometimes?"
+
+"Most always--most always. He ain't no account; but then he hain't
+ever done anything to hurt anybody. Just fishes a little, to get money
+to get drunk on--and loafs around considerable; but lord, we all do
+that--leastways most of us--preachers and such like. But he's kind of
+good--he give me half a fish, once, when there warn't enough for two;
+and lots of times he's kind of stood by me when I was out of luck."
+
+"Well, he's mended kites for me, Huck, and knitted hooks on to my
+line. I wish we could get him out of there."
+
+"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
+good; they'd ketch him again."
+
+"Yes--so they would. But I hate to hear 'em abuse him so like the
+dickens when he never done--that."
+
+"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
+villain in this country, and they wonder he wasn't ever hung before."
+
+"Yes, they talk like that, all the time. I've heard 'em say that if he
+was to get free they'd lynch him."
+
+"And they'd do it, too."
+
+The boys had a long talk, but it brought them little comfort. As the
+twilight drew on, they found themselves hanging about the neighborhood
+of the little isolated jail, perhaps with an undefined hope that
+something would happen that might clear away their difficulties. But
+nothing happened; there seemed to be no angels or fairies interested in
+this luckless captive.
+
+The boys did as they had often done before--went to the cell grating
+and gave Potter some tobacco and matches. He was on the ground floor
+and there were no guards.
+
+His gratitude for their gifts had always smote their consciences
+before--it cut deeper than ever, this time. They felt cowardly and
+treacherous to the last degree when Potter said:
+
+"You've been mighty good to me, boys--better'n anybody else in this
+town. And I don't forget it, I don't. Often I says to myself, says I,
+'I used to mend all the boys' kites and things, and show 'em where the
+good fishin' places was, and befriend 'em what I could, and now they've
+all forgot old Muff when he's in trouble; but Tom don't, and Huck
+don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
+boys, I done an awful thing--drunk and crazy at the time--that's the
+only way I account for it--and now I got to swing for it, and it's
+right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
+talk about that. I don't want to make YOU feel bad; you've befriended
+me. But what I want to say, is, don't YOU ever get drunk--then you won't
+ever get here. Stand a litter furder west--so--that's it; it's a prime
+comfort to see faces that's friendly when a body's in such a muck of
+trouble, and there don't none come here but yourn. Good friendly
+faces--good friendly faces. Git up on one another's backs and let me
+touch 'em. That's it. Shake hands--yourn'll come through the bars, but
+mine's too big. Little hands, and weak--but they've helped Muff Potter
+a power, and they'd help him more if they could."
+
+Tom went home miserable, and his dreams that night were full of
+horrors. The next day and the day after, he hung about the court-room,
+drawn by an almost irresistible impulse to go in, but forcing himself
+to stay out. Huck was having the same experience. They studiously
+avoided each other. Each wandered away, from time to time, but the same
+dismal fascination always brought them back presently. Tom kept his
+ears open when idlers sauntered out of the court-room, but invariably
+heard distressing news--the toils were closing more and more
+relentlessly around poor Potter. At the end of the second day the
+village talk was to the effect that Injun Joe's evidence stood firm and
+unshaken, and that there was not the slightest question as to what the
+jury's verdict would be.
+
+Tom was out late, that night, and came to bed through the window. He
+was in a tremendous state of excitement. It was hours before he got to
+sleep. All the village flocked to the court-house the next morning, for
+this was to be the great day. Both sexes were about equally represented
+in the packed audience. After a long wait the jury filed in and took
+their places; shortly afterward, Potter, pale and haggard, timid and
+hopeless, was brought in, with chains upon him, and seated where all
+the curious eyes could stare at him; no less conspicuous was Injun Joe,
+stolid as ever. There was another pause, and then the judge arrived and
+the sheriff proclaimed the opening of the court. The usual whisperings
+among the lawyers and gathering together of papers followed. These
+details and accompanying delays worked up an atmosphere of preparation
+that was as impressive as it was fascinating.
+
+Now a witness was called who testified that he found Muff Potter
+washing in the brook, at an early hour of the morning that the murder
+was discovered, and that he immediately sneaked away. After some
+further questioning, counsel for the prosecution said:
+
+"Take the witness."
+
+The prisoner raised his eyes for a moment, but dropped them again when
+his own counsel said:
+
+"I have no questions to ask him."
+
+The next witness proved the finding of the knife near the corpse.
+Counsel for the prosecution said:
+
+"Take the witness."
+
+"I have no questions to ask him," Potter's lawyer replied.
+
+A third witness swore he had often seen the knife in Potter's
+possession.
+
+"Take the witness."
+
+Counsel for Potter declined to question him. The faces of the audience
+began to betray annoyance. Did this attorney mean to throw away his
+client's life without an effort?
+
+Several witnesses deposed concerning Potter's guilty behavior when
+brought to the scene of the murder. They were allowed to leave the
+stand without being cross-questioned.
+
+Every detail of the damaging circumstances that occurred in the
+graveyard upon that morning which all present remembered so well was
+brought out by credible witnesses, but none of them were cross-examined
+by Potter's lawyer. The perplexity and dissatisfaction of the house
+expressed itself in murmurs and provoked a reproof from the bench.
+Counsel for the prosecution now said:
+
+"By the oaths of citizens whose simple word is above suspicion, we
+have fastened this awful crime, beyond all possibility of question,
+upon the unhappy prisoner at the bar. We rest our case here."
+
+A groan escaped from poor Potter, and he put his face in his hands and
+rocked his body softly to and fro, while a painful silence reigned in
+the court-room. Many men were moved, and many women's compassion
+testified itself in tears. Counsel for the defence rose and said:
+
+"Your honor, in our remarks at the opening of this trial, we
+foreshadowed our purpose to prove that our client did this fearful deed
+while under the influence of a blind and irresponsible delirium
+produced by drink. We have changed our mind. We shall not offer that
+plea." [Then to the clerk:] "Call Thomas Sawyer!"
+
+A puzzled amazement awoke in every face in the house, not even
+excepting Potter's. Every eye fastened itself with wondering interest
+upon Tom as he rose and took his place upon the stand. The boy looked
+wild enough, for he was badly scared. The oath was administered.
+
+"Thomas Sawyer, where were you on the seventeenth of June, about the
+hour of midnight?"
+
+Tom glanced at Injun Joe's iron face and his tongue failed him. The
+audience listened breathless, but the words refused to come. After a
+few moments, however, the boy got a little of his strength back, and
+managed to put enough of it into his voice to make part of the house
+hear:
+
+"In the graveyard!"
+
+"A little bit louder, please. Don't be afraid. You were--"
+
+"In the graveyard."
+
+A contemptuous smile flitted across Injun Joe's face.
+
+"Were you anywhere near Horse Williams' grave?"
+
+"Yes, sir."
+
+"Speak up--just a trifle louder. How near were you?"
+
+"Near as I am to you."
+
+"Were you hidden, or not?"
+
+"I was hid."
+
+"Where?"
+
+"Behind the elms that's on the edge of the grave."
+
+Injun Joe gave a barely perceptible start.
+
+"Any one with you?"
+
+"Yes, sir. I went there with--"
+
+"Wait--wait a moment. Never mind mentioning your companion's name. We
+will produce him at the proper time. Did you carry anything there with
+you."
+
+Tom hesitated and looked confused.
+
+"Speak out, my boy--don't be diffident. The truth is always
+respectable. What did you take there?"
+
+"Only a--a--dead cat."
+
+There was a ripple of mirth, which the court checked.
+
+"We will produce the skeleton of that cat. Now, my boy, tell us
+everything that occurred--tell it in your own way--don't skip anything,
+and don't be afraid."
+
+Tom began--hesitatingly at first, but as he warmed to his subject his
+words flowed more and more easily; in a little while every sound ceased
+but his own voice; every eye fixed itself upon him; with parted lips
+and bated breath the audience hung upon his words, taking no note of
+time, rapt in the ghastly fascinations of the tale. The strain upon
+pent emotion reached its climax when the boy said:
+
+"--and as the doctor fetched the board around and Muff Potter fell,
+Injun Joe jumped with the knife and--"
+
+Crash! Quick as lightning the half-breed sprang for a window, tore his
+way through all opposers, and was gone!
+
+
+
+CHAPTER XXIV
+
+TOM was a glittering hero once more--the pet of the old, the envy of
+the young. His name even went into immortal print, for the village
+paper magnified him. There were some that believed he would be
+President, yet, if he escaped hanging.
+
+As usual, the fickle, unreasoning world took Muff Potter to its bosom
+and fondled him as lavishly as it had abused him before. But that sort
+of conduct is to the world's credit; therefore it is not well to find
+fault with it.
+
+Tom's days were days of splendor and exultation to him, but his nights
+were seasons of horror. Injun Joe infested all his dreams, and always
+with doom in his eye. Hardly any temptation could persuade the boy to
+stir abroad after nightfall. Poor Huck was in the same state of
+wretchedness and terror, for Tom had told the whole story to the lawyer
+the night before the great day of the trial, and Huck was sore afraid
+that his share in the business might leak out, yet, notwithstanding
+Injun Joe's flight had saved him the suffering of testifying in court.
+The poor fellow had got the attorney to promise secrecy, but what of
+that? Since Tom's harassed conscience had managed to drive him to the
+lawyer's house by night and wring a dread tale from lips that had been
+sealed with the dismalest and most formidable of oaths, Huck's
+confidence in the human race was well-nigh obliterated.
+
+Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
+he wished he had sealed up his tongue.
+
+Half the time Tom was afraid Injun Joe would never be captured; the
+other half he was afraid he would be. He felt sure he never could draw
+a safe breath again until that man was dead and he had seen the corpse.
+
+Rewards had been offered, the country had been scoured, but no Injun
+Joe was found. One of those omniscient and awe-inspiring marvels, a
+detective, came up from St. Louis, moused around, shook his head,
+looked wise, and made that sort of astounding success which members of
+that craft usually achieve. That is to say, he "found a clew." But you
+can't hang a "clew" for murder, and so after that detective had got
+through and gone home, Tom felt just as insecure as he was before.
+
+The slow days drifted on, and each left behind it a slightly lightened
+weight of apprehension.
+
+
+
+CHAPTER XXV
+
+THERE comes a time in every rightly-constructed boy's life when he has
+a raging desire to go somewhere and dig for hidden treasure. This
+desire suddenly came upon Tom one day. He sallied out to find Joe
+Harper, but failed of success. Next he sought Ben Rogers; he had gone
+fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
+would answer. Tom took him to a private place and opened the matter to
+him confidentially. Huck was willing. Huck was always willing to take a
+hand in any enterprise that offered entertainment and required no
+capital, for he had a troublesome superabundance of that sort of time
+which is not money. "Where'll we dig?" said Huck.
+
+"Oh, most anywhere."
+
+"Why, is it hid all around?"
+
+"No, indeed it ain't. It's hid in mighty particular places, Huck
+--sometimes on islands, sometimes in rotten chests under the end of a
+limb of an old dead tree, just where the shadow falls at midnight; but
+mostly under the floor in ha'nted houses."
+
+"Who hides it?"
+
+"Why, robbers, of course--who'd you reckon? Sunday-school
+sup'rintendents?"
+
+"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
+a good time."
+
+"So would I. But robbers don't do that way. They always hide it and
+leave it there."
+
+"Don't they come after it any more?"
+
+"No, they think they will, but they generally forget the marks, or
+else they die. Anyway, it lays there a long time and gets rusty; and by
+and by somebody finds an old yellow paper that tells how to find the
+marks--a paper that's got to be ciphered over about a week because it's
+mostly signs and hy'roglyphics."
+
+"Hyro--which?"
+
+"Hy'roglyphics--pictures and things, you know, that don't seem to mean
+anything."
+
+"Have you got one of them papers, Tom?"
+
+"No."
+
+"Well then, how you going to find the marks?"
+
+"I don't want any marks. They always bury it under a ha'nted house or
+on an island, or under a dead tree that's got one limb sticking out.
+Well, we've tried Jackson's Island a little, and we can try it again
+some time; and there's the old ha'nted house up the Still-House branch,
+and there's lots of dead-limb trees--dead loads of 'em."
+
+"Is it under all of them?"
+
+"How you talk! No!"
+
+"Then how you going to know which one to go for?"
+
+"Go for all of 'em!"
+
+"Why, Tom, it'll take all summer."
+
+"Well, what of that? Suppose you find a brass pot with a hundred
+dollars in it, all rusty and gray, or rotten chest full of di'monds.
+How's that?"
+
+Huck's eyes glowed.
+
+"That's bully. Plenty bully enough for me. Just you gimme the hundred
+dollars and I don't want no di'monds."
+
+"All right. But I bet you I ain't going to throw off on di'monds. Some
+of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
+worth six bits or a dollar."
+
+"No! Is that so?"
+
+"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
+
+"Not as I remember."
+
+"Oh, kings have slathers of them."
+
+"Well, I don' know no kings, Tom."
+
+"I reckon you don't. But if you was to go to Europe you'd see a raft
+of 'em hopping around."
+
+"Do they hop?"
+
+"Hop?--your granny! No!"
+
+"Well, what did you say they did, for?"
+
+"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
+they want to hop for?--but I mean you'd just see 'em--scattered around,
+you know, in a kind of a general way. Like that old humpbacked Richard."
+
+"Richard? What's his other name?"
+
+"He didn't have any other name. Kings don't have any but a given name."
+
+"No?"
+
+"But they don't."
+
+"Well, if they like it, Tom, all right; but I don't want to be a king
+and have only just a given name, like a nigger. But say--where you
+going to dig first?"
+
+"Well, I don't know. S'pose we tackle that old dead-limb tree on the
+hill t'other side of Still-House branch?"
+
+"I'm agreed."
+
+So they got a crippled pick and a shovel, and set out on their
+three-mile tramp. They arrived hot and panting, and threw themselves
+down in the shade of a neighboring elm to rest and have a smoke.
+
+"I like this," said Tom.
+
+"So do I."
+
+"Say, Huck, if we find a treasure here, what you going to do with your
+share?"
+
+"Well, I'll have pie and a glass of soda every day, and I'll go to
+every circus that comes along. I bet I'll have a gay time."
+
+"Well, ain't you going to save any of it?"
+
+"Save it? What for?"
+
+"Why, so as to have something to live on, by and by."
+
+"Oh, that ain't any use. Pap would come back to thish-yer town some
+day and get his claws on it if I didn't hurry up, and I tell you he'd
+clean it out pretty quick. What you going to do with yourn, Tom?"
+
+"I'm going to buy a new drum, and a sure-'nough sword, and a red
+necktie and a bull pup, and get married."
+
+"Married!"
+
+"That's it."
+
+"Tom, you--why, you ain't in your right mind."
+
+"Wait--you'll see."
+
+"Well, that's the foolishest thing you could do. Look at pap and my
+mother. Fight! Why, they used to fight all the time. I remember, mighty
+well."
+
+"That ain't anything. The girl I'm going to marry won't fight."
+
+"Tom, I reckon they're all alike. They'll all comb a body. Now you
+better think 'bout this awhile. I tell you you better. What's the name
+of the gal?"
+
+"It ain't a gal at all--it's a girl."
+
+"It's all the same, I reckon; some says gal, some says girl--both's
+right, like enough. Anyway, what's her name, Tom?"
+
+"I'll tell you some time--not now."
+
+"All right--that'll do. Only if you get married I'll be more lonesomer
+than ever."
+
+"No you won't. You'll come and live with me. Now stir out of this and
+we'll go to digging."
+
+They worked and sweated for half an hour. No result. They toiled
+another half-hour. Still no result. Huck said:
+
+"Do they always bury it as deep as this?"
+
+"Sometimes--not always. Not generally. I reckon we haven't got the
+right place."
+
+So they chose a new spot and began again. The labor dragged a little,
+but still they made progress. They pegged away in silence for some
+time. Finally Huck leaned on his shovel, swabbed the beaded drops from
+his brow with his sleeve, and said:
+
+"Where you going to dig next, after we get this one?"
+
+"I reckon maybe we'll tackle the old tree that's over yonder on
+Cardiff Hill back of the widow's."
+
+"I reckon that'll be a good one. But won't the widow take it away from
+us, Tom? It's on her land."
+
+"SHE take it away! Maybe she'd like to try it once. Whoever finds one
+of these hid treasures, it belongs to him. It don't make any difference
+whose land it's on."
+
+That was satisfactory. The work went on. By and by Huck said:
+
+"Blame it, we must be in the wrong place again. What do you think?"
+
+"It is mighty curious, Huck. I don't understand it. Sometimes witches
+interfere. I reckon maybe that's what's the trouble now."
+
+"Shucks! Witches ain't got no power in the daytime."
+
+"Well, that's so. I didn't think of that. Oh, I know what the matter
+is! What a blamed lot of fools we are! You got to find out where the
+shadow of the limb falls at midnight, and that's where you dig!"
+
+"Then consound it, we've fooled away all this work for nothing. Now
+hang it all, we got to come back in the night. It's an awful long way.
+Can you get out?"
+
+"I bet I will. We've got to do it to-night, too, because if somebody
+sees these holes they'll know in a minute what's here and they'll go
+for it."
+
+"Well, I'll come around and maow to-night."
+
+"All right. Let's hide the tools in the bushes."
+
+The boys were there that night, about the appointed time. They sat in
+the shadow waiting. It was a lonely place, and an hour made solemn by
+old traditions. Spirits whispered in the rustling leaves, ghosts lurked
+in the murky nooks, the deep baying of a hound floated up out of the
+distance, an owl answered with his sepulchral note. The boys were
+subdued by these solemnities, and talked little. By and by they judged
+that twelve had come; they marked where the shadow fell, and began to
+dig. Their hopes commenced to rise. Their interest grew stronger, and
+their industry kept pace with it. The hole deepened and still deepened,
+but every time their hearts jumped to hear the pick strike upon
+something, they only suffered a new disappointment. It was only a stone
+or a chunk. At last Tom said:
+
+"It ain't any use, Huck, we're wrong again."
+
+"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
+
+"I know it, but then there's another thing."
+
+"What's that?".
+
+"Why, we only guessed at the time. Like enough it was too late or too
+early."
+
+Huck dropped his shovel.
+
+"That's it," said he. "That's the very trouble. We got to give this
+one up. We can't ever tell the right time, and besides this kind of
+thing's too awful, here this time of night with witches and ghosts
+a-fluttering around so. I feel as if something's behind me all the time;
+and I'm afeard to turn around, becuz maybe there's others in front
+a-waiting for a chance. I been creeping all over, ever since I got here."
+
+"Well, I've been pretty much so, too, Huck. They most always put in a
+dead man when they bury a treasure under a tree, to look out for it."
+
+"Lordy!"
+
+"Yes, they do. I've always heard that."
+
+"Tom, I don't like to fool around much where there's dead people. A
+body's bound to get into trouble with 'em, sure."
+
+"I don't like to stir 'em up, either. S'pose this one here was to
+stick his skull out and say something!"
+
+"Don't Tom! It's awful."
+
+"Well, it just is. Huck, I don't feel comfortable a bit."
+
+"Say, Tom, let's give this place up, and try somewheres else."
+
+"All right, I reckon we better."
+
+"What'll it be?"
+
+Tom considered awhile; and then said:
+
+"The ha'nted house. That's it!"
+
+"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
+worse'n dead people. Dead people might talk, maybe, but they don't come
+sliding around in a shroud, when you ain't noticing, and peep over your
+shoulder all of a sudden and grit their teeth, the way a ghost does. I
+couldn't stand such a thing as that, Tom--nobody could."
+
+"Yes, but, Huck, ghosts don't travel around only at night. They won't
+hender us from digging there in the daytime."
+
+"Well, that's so. But you know mighty well people don't go about that
+ha'nted house in the day nor the night."
+
+"Well, that's mostly because they don't like to go where a man's been
+murdered, anyway--but nothing's ever been seen around that house except
+in the night--just some blue lights slipping by the windows--no regular
+ghosts."
+
+"Well, where you see one of them blue lights flickering around, Tom,
+you can bet there's a ghost mighty close behind it. It stands to
+reason. Becuz you know that they don't anybody but ghosts use 'em."
+
+"Yes, that's so. But anyway they don't come around in the daytime, so
+what's the use of our being afeard?"
+
+"Well, all right. We'll tackle the ha'nted house if you say so--but I
+reckon it's taking chances."
+
+They had started down the hill by this time. There in the middle of
+the moonlit valley below them stood the "ha'nted" house, utterly
+isolated, its fences gone long ago, rank weeds smothering the very
+doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
+corner of the roof caved in. The boys gazed awhile, half expecting to
+see a blue light flit past a window; then talking in a low tone, as
+befitted the time and the circumstances, they struck far off to the
+right, to give the haunted house a wide berth, and took their way
+homeward through the woods that adorned the rearward side of Cardiff
+Hill.
+
+
+
+CHAPTER XXVI
+
+ABOUT noon the next day the boys arrived at the dead tree; they had
+come for their tools. Tom was impatient to go to the haunted house;
+Huck was measurably so, also--but suddenly said:
+
+"Lookyhere, Tom, do you know what day it is?"
+
+Tom mentally ran over the days of the week, and then quickly lifted
+his eyes with a startled look in them--
+
+"My! I never once thought of it, Huck!"
+
+"Well, I didn't neither, but all at once it popped onto me that it was
+Friday."
+
+"Blame it, a body can't be too careful, Huck. We might 'a' got into an
+awful scrape, tackling such a thing on a Friday."
+
+"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
+Friday ain't."
+
+"Any fool knows that. I don't reckon YOU was the first that found it
+out, Huck."
+
+"Well, I never said I was, did I? And Friday ain't all, neither. I had
+a rotten bad dream last night--dreampt about rats."
+
+"No! Sure sign of trouble. Did they fight?"
+
+"No."
+
+"Well, that's good, Huck. When they don't fight it's only a sign that
+there's trouble around, you know. All we got to do is to look mighty
+sharp and keep out of it. We'll drop this thing for to-day, and play.
+Do you know Robin Hood, Huck?"
+
+"No. Who's Robin Hood?"
+
+"Why, he was one of the greatest men that was ever in England--and the
+best. He was a robber."
+
+"Cracky, I wisht I was. Who did he rob?"
+
+"Only sheriffs and bishops and rich people and kings, and such like.
+But he never bothered the poor. He loved 'em. He always divided up with
+'em perfectly square."
+
+"Well, he must 'a' been a brick."
+
+"I bet you he was, Huck. Oh, he was the noblest man that ever was.
+They ain't any such men now, I can tell you. He could lick any man in
+England, with one hand tied behind him; and he could take his yew bow
+and plug a ten-cent piece every time, a mile and a half."
+
+"What's a YEW bow?"
+
+"I don't know. It's some kind of a bow, of course. And if he hit that
+dime only on the edge he would set down and cry--and curse. But we'll
+play Robin Hood--it's nobby fun. I'll learn you."
+
+"I'm agreed."
+
+So they played Robin Hood all the afternoon, now and then casting a
+yearning eye down upon the haunted house and passing a remark about the
+morrow's prospects and possibilities there. As the sun began to sink
+into the west they took their way homeward athwart the long shadows of
+the trees and soon were buried from sight in the forests of Cardiff
+Hill.
+
+On Saturday, shortly after noon, the boys were at the dead tree again.
+They had a smoke and a chat in the shade, and then dug a little in
+their last hole, not with great hope, but merely because Tom said there
+were so many cases where people had given up a treasure after getting
+down within six inches of it, and then somebody else had come along and
+turned it up with a single thrust of a shovel. The thing failed this
+time, however, so the boys shouldered their tools and went away feeling
+that they had not trifled with fortune, but had fulfilled all the
+requirements that belong to the business of treasure-hunting.
+
+When they reached the haunted house there was something so weird and
+grisly about the dead silence that reigned there under the baking sun,
+and something so depressing about the loneliness and desolation of the
+place, that they were afraid, for a moment, to venture in. Then they
+crept to the door and took a trembling peep. They saw a weed-grown,
+floorless room, unplastered, an ancient fireplace, vacant windows, a
+ruinous staircase; and here, there, and everywhere hung ragged and
+abandoned cobwebs. They presently entered, softly, with quickened
+pulses, talking in whispers, ears alert to catch the slightest sound,
+and muscles tense and ready for instant retreat.
+
+In a little while familiarity modified their fears and they gave the
+place a critical and interested examination, rather admiring their own
+boldness, and wondering at it, too. Next they wanted to look up-stairs.
+This was something like cutting off retreat, but they got to daring
+each other, and of course there could be but one result--they threw
+their tools into a corner and made the ascent. Up there were the same
+signs of decay. In one corner they found a closet that promised
+mystery, but the promise was a fraud--there was nothing in it. Their
+courage was up now and well in hand. They were about to go down and
+begin work when--
+
+"Sh!" said Tom.
+
+"What is it?" whispered Huck, blanching with fright.
+
+"Sh!... There!... Hear it?"
+
+"Yes!... Oh, my! Let's run!"
+
+"Keep still! Don't you budge! They're coming right toward the door."
+
+The boys stretched themselves upon the floor with their eyes to
+knot-holes in the planking, and lay waiting, in a misery of fear.
+
+"They've stopped.... No--coming.... Here they are. Don't whisper
+another word, Huck. My goodness, I wish I was out of this!"
+
+Two men entered. Each boy said to himself: "There's the old deaf and
+dumb Spaniard that's been about town once or twice lately--never saw
+t'other man before."
+
+"T'other" was a ragged, unkempt creature, with nothing very pleasant
+in his face. The Spaniard was wrapped in a serape; he had bushy white
+whiskers; long white hair flowed from under his sombrero, and he wore
+green goggles. When they came in, "t'other" was talking in a low voice;
+they sat down on the ground, facing the door, with their backs to the
+wall, and the speaker continued his remarks. His manner became less
+guarded and his words more distinct as he proceeded:
+
+"No," said he, "I've thought it all over, and I don't like it. It's
+dangerous."
+
+"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
+surprise of the boys. "Milksop!"
+
+This voice made the boys gasp and quake. It was Injun Joe's! There was
+silence for some time. Then Joe said:
+
+"What's any more dangerous than that job up yonder--but nothing's come
+of it."
+
+"That's different. Away up the river so, and not another house about.
+'Twon't ever be known that we tried, anyway, long as we didn't succeed."
+
+"Well, what's more dangerous than coming here in the daytime!--anybody
+would suspicion us that saw us."
+
+"I know that. But there warn't any other place as handy after that
+fool of a job. I want to quit this shanty. I wanted to yesterday, only
+it warn't any use trying to stir out of here, with those infernal boys
+playing over there on the hill right in full view."
+
+"Those infernal boys" quaked again under the inspiration of this
+remark, and thought how lucky it was that they had remembered it was
+Friday and concluded to wait a day. They wished in their hearts they
+had waited a year.
+
+The two men got out some food and made a luncheon. After a long and
+thoughtful silence, Injun Joe said:
+
+"Look here, lad--you go back up the river where you belong. Wait there
+till you hear from me. I'll take the chances on dropping into this town
+just once more, for a look. We'll do that 'dangerous' job after I've
+spied around a little and think things look well for it. Then for
+Texas! We'll leg it together!"
+
+This was satisfactory. Both men presently fell to yawning, and Injun
+Joe said:
+
+"I'm dead for sleep! It's your turn to watch."
+
+He curled down in the weeds and soon began to snore. His comrade
+stirred him once or twice and he became quiet. Presently the watcher
+began to nod; his head drooped lower and lower, both men began to snore
+now.
+
+The boys drew a long, grateful breath. Tom whispered:
+
+"Now's our chance--come!"
+
+Huck said:
+
+"I can't--I'd die if they was to wake."
+
+Tom urged--Huck held back. At last Tom rose slowly and softly, and
+started alone. But the first step he made wrung such a hideous creak
+from the crazy floor that he sank down almost dead with fright. He
+never made a second attempt. The boys lay there counting the dragging
+moments till it seemed to them that time must be done and eternity
+growing gray; and then they were grateful to note that at last the sun
+was setting.
+
+Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
+upon his comrade, whose head was drooping upon his knees--stirred him
+up with his foot and said:
+
+"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
+happened."
+
+"My! have I been asleep?"
+
+"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
+do with what little swag we've got left?"
+
+"I don't know--leave it here as we've always done, I reckon. No use to
+take it away till we start south. Six hundred and fifty in silver's
+something to carry."
+
+"Well--all right--it won't matter to come here once more."
+
+"No--but I'd say come in the night as we used to do--it's better."
+
+"Yes: but look here; it may be a good while before I get the right
+chance at that job; accidents might happen; 'tain't in such a very good
+place; we'll just regularly bury it--and bury it deep."
+
+"Good idea," said the comrade, who walked across the room, knelt down,
+raised one of the rearward hearth-stones and took out a bag that
+jingled pleasantly. He subtracted from it twenty or thirty dollars for
+himself and as much for Injun Joe, and passed the bag to the latter,
+who was on his knees in the corner, now, digging with his bowie-knife.
+
+The boys forgot all their fears, all their miseries in an instant.
+With gloating eyes they watched every movement. Luck!--the splendor of
+it was beyond all imagination! Six hundred dollars was money enough to
+make half a dozen boys rich! Here was treasure-hunting under the
+happiest auspices--there would not be any bothersome uncertainty as to
+where to dig. They nudged each other every moment--eloquent nudges and
+easily understood, for they simply meant--"Oh, but ain't you glad NOW
+we're here!"
+
+Joe's knife struck upon something.
+
+"Hello!" said he.
+
+"What is it?" said his comrade.
+
+"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
+we'll see what it's here for. Never mind, I've broke a hole."
+
+He reached his hand in and drew it out--
+
+"Man, it's money!"
+
+The two men examined the handful of coins. They were gold. The boys
+above were as excited as themselves, and as delighted.
+
+Joe's comrade said:
+
+"We'll make quick work of this. There's an old rusty pick over amongst
+the weeds in the corner the other side of the fireplace--I saw it a
+minute ago."
+
+He ran and brought the boys' pick and shovel. Injun Joe took the pick,
+looked it over critically, shook his head, muttered something to
+himself, and then began to use it. The box was soon unearthed. It was
+not very large; it was iron bound and had been very strong before the
+slow years had injured it. The men contemplated the treasure awhile in
+blissful silence.
+
+"Pard, there's thousands of dollars here," said Injun Joe.
+
+"'Twas always said that Murrel's gang used to be around here one
+summer," the stranger observed.
+
+"I know it," said Injun Joe; "and this looks like it, I should say."
+
+"Now you won't need to do that job."
+
+The half-breed frowned. Said he:
+
+"You don't know me. Least you don't know all about that thing. 'Tain't
+robbery altogether--it's REVENGE!" and a wicked light flamed in his
+eyes. "I'll need your help in it. When it's finished--then Texas. Go
+home to your Nance and your kids, and stand by till you hear from me."
+
+"Well--if you say so; what'll we do with this--bury it again?"
+
+"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
+[Profound distress overhead.] I'd nearly forgot. That pick had fresh
+earth on it! [The boys were sick with terror in a moment.] What
+business has a pick and a shovel here? What business with fresh earth
+on them? Who brought them here--and where are they gone? Have you heard
+anybody?--seen anybody? What! bury it again and leave them to come and
+see the ground disturbed? Not exactly--not exactly. We'll take it to my
+den."
+
+"Why, of course! Might have thought of that before. You mean Number
+One?"
+
+"No--Number Two--under the cross. The other place is bad--too common."
+
+"All right. It's nearly dark enough to start."
+
+Injun Joe got up and went about from window to window cautiously
+peeping out. Presently he said:
+
+"Who could have brought those tools here? Do you reckon they can be
+up-stairs?"
+
+The boys' breath forsook them. Injun Joe put his hand on his knife,
+halted a moment, undecided, and then turned toward the stairway. The
+boys thought of the closet, but their strength was gone. The steps came
+creaking up the stairs--the intolerable distress of the situation woke
+the stricken resolution of the lads--they were about to spring for the
+closet, when there was a crash of rotten timbers and Injun Joe landed
+on the ground amid the debris of the ruined stairway. He gathered
+himself up cursing, and his comrade said:
+
+"Now what's the use of all that? If it's anybody, and they're up
+there, let them STAY there--who cares? If they want to jump down, now,
+and get into trouble, who objects? It will be dark in fifteen minutes
+--and then let them follow us if they want to. I'm willing. In my
+opinion, whoever hove those things in here caught a sight of us and
+took us for ghosts or devils or something. I'll bet they're running
+yet."
+
+Joe grumbled awhile; then he agreed with his friend that what daylight
+was left ought to be economized in getting things ready for leaving.
+Shortly afterward they slipped out of the house in the deepening
+twilight, and moved toward the river with their precious box.
+
+Tom and Huck rose up, weak but vastly relieved, and stared after them
+through the chinks between the logs of the house. Follow? Not they.
+They were content to reach ground again without broken necks, and take
+the townward track over the hill. They did not talk much. They were too
+much absorbed in hating themselves--hating the ill luck that made them
+take the spade and the pick there. But for that, Injun Joe never would
+have suspected. He would have hidden the silver with the gold to wait
+there till his "revenge" was satisfied, and then he would have had the
+misfortune to find that money turn up missing. Bitter, bitter luck that
+the tools were ever brought there!
+
+They resolved to keep a lookout for that Spaniard when he should come
+to town spying out for chances to do his revengeful job, and follow him
+to "Number Two," wherever that might be. Then a ghastly thought
+occurred to Tom.
+
+"Revenge? What if he means US, Huck!"
+
+"Oh, don't!" said Huck, nearly fainting.
+
+They talked it all over, and as they entered town they agreed to
+believe that he might possibly mean somebody else--at least that he
+might at least mean nobody but Tom, since only Tom had testified.
+
+Very, very small comfort it was to Tom to be alone in danger! Company
+would be a palpable improvement, he thought.
+
+
+
+CHAPTER XXVII
+
+THE adventure of the day mightily tormented Tom's dreams that night.
+Four times he had his hands on that rich treasure and four times it
+wasted to nothingness in his fingers as sleep forsook him and
+wakefulness brought back the hard reality of his misfortune. As he lay
+in the early morning recalling the incidents of his great adventure, he
+noticed that they seemed curiously subdued and far away--somewhat as if
+they had happened in another world, or in a time long gone by. Then it
+occurred to him that the great adventure itself must be a dream! There
+was one very strong argument in favor of this idea--namely, that the
+quantity of coin he had seen was too vast to be real. He had never seen
+as much as fifty dollars in one mass before, and he was like all boys
+of his age and station in life, in that he imagined that all references
+to "hundreds" and "thousands" were mere fanciful forms of speech, and
+that no such sums really existed in the world. He never had supposed
+for a moment that so large a sum as a hundred dollars was to be found
+in actual money in any one's possession. If his notions of hidden
+treasure had been analyzed, they would have been found to consist of a
+handful of real dimes and a bushel of vague, splendid, ungraspable
+dollars.
+
+But the incidents of his adventure grew sensibly sharper and clearer
+under the attrition of thinking them over, and so he presently found
+himself leaning to the impression that the thing might not have been a
+dream, after all. This uncertainty must be swept away. He would snatch
+a hurried breakfast and go and find Huck. Huck was sitting on the
+gunwale of a flatboat, listlessly dangling his feet in the water and
+looking very melancholy. Tom concluded to let Huck lead up to the
+subject. If he did not do it, then the adventure would be proved to
+have been only a dream.
+
+"Hello, Huck!"
+
+"Hello, yourself."
+
+Silence, for a minute.
+
+"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
+the money. Oh, ain't it awful!"
+
+"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
+Dog'd if I don't, Huck."
+
+"What ain't a dream?"
+
+"Oh, that thing yesterday. I been half thinking it was."
+
+"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
+it was! I've had dreams enough all night--with that patch-eyed Spanish
+devil going for me all through 'em--rot him!"
+
+"No, not rot him. FIND him! Track the money!"
+
+"Tom, we'll never find him. A feller don't have only one chance for
+such a pile--and that one's lost. I'd feel mighty shaky if I was to see
+him, anyway."
+
+"Well, so'd I; but I'd like to see him, anyway--and track him out--to
+his Number Two."
+
+"Number Two--yes, that's it. I been thinking 'bout that. But I can't
+make nothing out of it. What do you reckon it is?"
+
+"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
+
+"Goody!... No, Tom, that ain't it. If it is, it ain't in this
+one-horse town. They ain't no numbers here."
+
+"Well, that's so. Lemme think a minute. Here--it's the number of a
+room--in a tavern, you know!"
+
+"Oh, that's the trick! They ain't only two taverns. We can find out
+quick."
+
+"You stay here, Huck, till I come."
+
+Tom was off at once. He did not care to have Huck's company in public
+places. He was gone half an hour. He found that in the best tavern, No.
+2 had long been occupied by a young lawyer, and was still so occupied.
+In the less ostentatious house, No. 2 was a mystery. The
+tavern-keeper's young son said it was kept locked all the time, and he
+never saw anybody go into it or come out of it except at night; he did
+not know any particular reason for this state of things; had had some
+little curiosity, but it was rather feeble; had made the most of the
+mystery by entertaining himself with the idea that that room was
+"ha'nted"; had noticed that there was a light in there the night before.
+
+"That's what I've found out, Huck. I reckon that's the very No. 2
+we're after."
+
+"I reckon it is, Tom. Now what you going to do?"
+
+"Lemme think."
+
+Tom thought a long time. Then he said:
+
+"I'll tell you. The back door of that No. 2 is the door that comes out
+into that little close alley between the tavern and the old rattle trap
+of a brick store. Now you get hold of all the door-keys you can find,
+and I'll nip all of auntie's, and the first dark night we'll go there
+and try 'em. And mind you, keep a lookout for Injun Joe, because he
+said he was going to drop into town and spy around once more for a
+chance to get his revenge. If you see him, you just follow him; and if
+he don't go to that No. 2, that ain't the place."
+
+"Lordy, I don't want to foller him by myself!"
+
+"Why, it'll be night, sure. He mightn't ever see you--and if he did,
+maybe he'd never think anything."
+
+"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
+I'll try."
+
+"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
+out he couldn't get his revenge, and be going right after that money."
+
+"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
+
+"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
+
+
+
+CHAPTER XXVIII
+
+THAT night Tom and Huck were ready for their adventure. They hung
+about the neighborhood of the tavern until after nine, one watching the
+alley at a distance and the other the tavern door. Nobody entered the
+alley or left it; nobody resembling the Spaniard entered or left the
+tavern door. The night promised to be a fair one; so Tom went home with
+the understanding that if a considerable degree of darkness came on,
+Huck was to come and "maow," whereupon he would slip out and try the
+keys. But the night remained clear, and Huck closed his watch and
+retired to bed in an empty sugar hogshead about twelve.
+
+Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
+night promised better. Tom slipped out in good season with his aunt's
+old tin lantern, and a large towel to blindfold it with. He hid the
+lantern in Huck's sugar hogshead and the watch began. An hour before
+midnight the tavern closed up and its lights (the only ones
+thereabouts) were put out. No Spaniard had been seen. Nobody had
+entered or left the alley. Everything was auspicious. The blackness of
+darkness reigned, the perfect stillness was interrupted only by
+occasional mutterings of distant thunder.
+
+Tom got his lantern, lit it in the hogshead, wrapped it closely in the
+towel, and the two adventurers crept in the gloom toward the tavern.
+Huck stood sentry and Tom felt his way into the alley. Then there was a
+season of waiting anxiety that weighed upon Huck's spirits like a
+mountain. He began to wish he could see a flash from the lantern--it
+would frighten him, but it would at least tell him that Tom was alive
+yet. It seemed hours since Tom had disappeared. Surely he must have
+fainted; maybe he was dead; maybe his heart had burst under terror and
+excitement. In his uneasiness Huck found himself drawing closer and
+closer to the alley; fearing all sorts of dreadful things, and
+momentarily expecting some catastrophe to happen that would take away
+his breath. There was not much to take away, for he seemed only able to
+inhale it by thimblefuls, and his heart would soon wear itself out, the
+way it was beating. Suddenly there was a flash of light and Tom came
+tearing by him: "Run!" said he; "run, for your life!"
+
+He needn't have repeated it; once was enough; Huck was making thirty
+or forty miles an hour before the repetition was uttered. The boys
+never stopped till they reached the shed of a deserted slaughter-house
+at the lower end of the village. Just as they got within its shelter
+the storm burst and the rain poured down. As soon as Tom got his breath
+he said:
+
+"Huck, it was awful! I tried two of the keys, just as soft as I could;
+but they seemed to make such a power of racket that I couldn't hardly
+get my breath I was so scared. They wouldn't turn in the lock, either.
+Well, without noticing what I was doing, I took hold of the knob, and
+open comes the door! It warn't locked! I hopped in, and shook off the
+towel, and, GREAT CAESAR'S GHOST!"
+
+"What!--what'd you see, Tom?"
+
+"Huck, I most stepped onto Injun Joe's hand!"
+
+"No!"
+
+"Yes! He was lying there, sound asleep on the floor, with his old
+patch on his eye and his arms spread out."
+
+"Lordy, what did you do? Did he wake up?"
+
+"No, never budged. Drunk, I reckon. I just grabbed that towel and
+started!"
+
+"I'd never 'a' thought of the towel, I bet!"
+
+"Well, I would. My aunt would make me mighty sick if I lost it."
+
+"Say, Tom, did you see that box?"
+
+"Huck, I didn't wait to look around. I didn't see the box, I didn't
+see the cross. I didn't see anything but a bottle and a tin cup on the
+floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
+room. Don't you see, now, what's the matter with that ha'nted room?"
+
+"How?"
+
+"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
+got a ha'nted room, hey, Huck?"
+
+"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
+say, Tom, now's a mighty good time to get that box, if Injun Joe's
+drunk."
+
+"It is, that! You try it!"
+
+Huck shuddered.
+
+"Well, no--I reckon not."
+
+"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
+enough. If there'd been three, he'd be drunk enough and I'd do it."
+
+There was a long pause for reflection, and then Tom said:
+
+"Lookyhere, Huck, less not try that thing any more till we know Injun
+Joe's not in there. It's too scary. Now, if we watch every night, we'll
+be dead sure to see him go out, some time or other, and then we'll
+snatch that box quicker'n lightning."
+
+"Well, I'm agreed. I'll watch the whole night long, and I'll do it
+every night, too, if you'll do the other part of the job."
+
+"All right, I will. All you got to do is to trot up Hooper Street a
+block and maow--and if I'm asleep, you throw some gravel at the window
+and that'll fetch me."
+
+"Agreed, and good as wheat!"
+
+"Now, Huck, the storm's over, and I'll go home. It'll begin to be
+daylight in a couple of hours. You go back and watch that long, will
+you?"
+
+"I said I would, Tom, and I will. I'll ha'nt that tavern every night
+for a year! I'll sleep all day and I'll stand watch all night."
+
+"That's all right. Now, where you going to sleep?"
+
+"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
+Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
+any time I ask him he gives me a little something to eat if he can
+spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
+ever act as if I was above him. Sometime I've set right down and eat
+WITH him. But you needn't tell that. A body's got to do things when
+he's awful hungry he wouldn't want to do as a steady thing."
+
+"Well, if I don't want you in the daytime, I'll let you sleep. I won't
+come bothering around. Any time you see something's up, in the night,
+just skip right around and maow."
+
+
+
+CHAPTER XXIX
+
+THE first thing Tom heard on Friday morning was a glad piece of news
+--Judge Thatcher's family had come back to town the night before. Both
+Injun Joe and the treasure sunk into secondary importance for a moment,
+and Becky took the chief place in the boy's interest. He saw her and
+they had an exhausting good time playing "hi-spy" and "gully-keeper"
+with a crowd of their school-mates. The day was completed and crowned
+in a peculiarly satisfactory way: Becky teased her mother to appoint
+the next day for the long-promised and long-delayed picnic, and she
+consented. The child's delight was boundless; and Tom's not more
+moderate. The invitations were sent out before sunset, and straightway
+the young folks of the village were thrown into a fever of preparation
+and pleasurable anticipation. Tom's excitement enabled him to keep
+awake until a pretty late hour, and he had good hopes of hearing Huck's
+"maow," and of having his treasure to astonish Becky and the picnickers
+with, next day; but he was disappointed. No signal came that night.
+
+Morning came, eventually, and by ten or eleven o'clock a giddy and
+rollicking company were gathered at Judge Thatcher's, and everything
+was ready for a start. It was not the custom for elderly people to mar
+the picnics with their presence. The children were considered safe
+enough under the wings of a few young ladies of eighteen and a few
+young gentlemen of twenty-three or thereabouts. The old steam ferryboat
+was chartered for the occasion; presently the gay throng filed up the
+main street laden with provision-baskets. Sid was sick and had to miss
+the fun; Mary remained at home to entertain him. The last thing Mrs.
+Thatcher said to Becky, was:
+
+"You'll not get back till late. Perhaps you'd better stay all night
+with some of the girls that live near the ferry-landing, child."
+
+"Then I'll stay with Susy Harper, mamma."
+
+"Very well. And mind and behave yourself and don't be any trouble."
+
+Presently, as they tripped along, Tom said to Becky:
+
+"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
+we'll climb right up the hill and stop at the Widow Douglas'. She'll
+have ice-cream! She has it most every day--dead loads of it. And she'll
+be awful glad to have us."
+
+"Oh, that will be fun!"
+
+Then Becky reflected a moment and said:
+
+"But what will mamma say?"
+
+"How'll she ever know?"
+
+The girl turned the idea over in her mind, and said reluctantly:
+
+"I reckon it's wrong--but--"
+
+"But shucks! Your mother won't know, and so what's the harm? All she
+wants is that you'll be safe; and I bet you she'd 'a' said go there if
+she'd 'a' thought of it. I know she would!"
+
+The Widow Douglas' splendid hospitality was a tempting bait. It and
+Tom's persuasions presently carried the day. So it was decided to say
+nothing anybody about the night's programme. Presently it occurred to
+Tom that maybe Huck might come this very night and give the signal. The
+thought took a deal of the spirit out of his anticipations. Still he
+could not bear to give up the fun at Widow Douglas'. And why should he
+give it up, he reasoned--the signal did not come the night before, so
+why should it be any more likely to come to-night? The sure fun of the
+evening outweighed the uncertain treasure; and, boy-like, he determined
+to yield to the stronger inclination and not allow himself to think of
+the box of money another time that day.
+
+Three miles below town the ferryboat stopped at the mouth of a woody
+hollow and tied up. The crowd swarmed ashore and soon the forest
+distances and craggy heights echoed far and near with shoutings and
+laughter. All the different ways of getting hot and tired were gone
+through with, and by-and-by the rovers straggled back to camp fortified
+with responsible appetites, and then the destruction of the good things
+began. After the feast there was a refreshing season of rest and chat
+in the shade of spreading oaks. By-and-by somebody shouted:
+
+"Who's ready for the cave?"
+
+Everybody was. Bundles of candles were procured, and straightway there
+was a general scamper up the hill. The mouth of the cave was up the
+hillside--an opening shaped like a letter A. Its massive oaken door
+stood unbarred. Within was a small chamber, chilly as an ice-house, and
+walled by Nature with solid limestone that was dewy with a cold sweat.
+It was romantic and mysterious to stand here in the deep gloom and look
+out upon the green valley shining in the sun. But the impressiveness of
+the situation quickly wore off, and the romping began again. The moment
+a candle was lighted there was a general rush upon the owner of it; a
+struggle and a gallant defence followed, but the candle was soon
+knocked down or blown out, and then there was a glad clamor of laughter
+and a new chase. But all things have an end. By-and-by the procession
+went filing down the steep descent of the main avenue, the flickering
+rank of lights dimly revealing the lofty walls of rock almost to their
+point of junction sixty feet overhead. This main avenue was not more
+than eight or ten feet wide. Every few steps other lofty and still
+narrower crevices branched from it on either hand--for McDougal's cave
+was but a vast labyrinth of crooked aisles that ran into each other and
+out again and led nowhere. It was said that one might wander days and
+nights together through its intricate tangle of rifts and chasms, and
+never find the end of the cave; and that he might go down, and down,
+and still down, into the earth, and it was just the same--labyrinth
+under labyrinth, and no end to any of them. No man "knew" the cave.
+That was an impossible thing. Most of the young men knew a portion of
+it, and it was not customary to venture much beyond this known portion.
+Tom Sawyer knew as much of the cave as any one.
+
+The procession moved along the main avenue some three-quarters of a
+mile, and then groups and couples began to slip aside into branch
+avenues, fly along the dismal corridors, and take each other by
+surprise at points where the corridors joined again. Parties were able
+to elude each other for the space of half an hour without going beyond
+the "known" ground.
+
+By-and-by, one group after another came straggling back to the mouth
+of the cave, panting, hilarious, smeared from head to foot with tallow
+drippings, daubed with clay, and entirely delighted with the success of
+the day. Then they were astonished to find that they had been taking no
+note of time and that night was about at hand. The clanging bell had
+been calling for half an hour. However, this sort of close to the day's
+adventures was romantic and therefore satisfactory. When the ferryboat
+with her wild freight pushed into the stream, nobody cared sixpence for
+the wasted time but the captain of the craft.
+
+Huck was already upon his watch when the ferryboat's lights went
+glinting past the wharf. He heard no noise on board, for the young
+people were as subdued and still as people usually are who are nearly
+tired to death. He wondered what boat it was, and why she did not stop
+at the wharf--and then he dropped her out of his mind and put his
+attention upon his business. The night was growing cloudy and dark. Ten
+o'clock came, and the noise of vehicles ceased, scattered lights began
+to wink out, all straggling foot-passengers disappeared, the village
+betook itself to its slumbers and left the small watcher alone with the
+silence and the ghosts. Eleven o'clock came, and the tavern lights were
+put out; darkness everywhere, now. Huck waited what seemed a weary long
+time, but nothing happened. His faith was weakening. Was there any use?
+Was there really any use? Why not give it up and turn in?
+
+A noise fell upon his ear. He was all attention in an instant. The
+alley door closed softly. He sprang to the corner of the brick store.
+The next moment two men brushed by him, and one seemed to have
+something under his arm. It must be that box! So they were going to
+remove the treasure. Why call Tom now? It would be absurd--the men
+would get away with the box and never be found again. No, he would
+stick to their wake and follow them; he would trust to the darkness for
+security from discovery. So communing with himself, Huck stepped out
+and glided along behind the men, cat-like, with bare feet, allowing
+them to keep just far enough ahead not to be invisible.
+
+They moved up the river street three blocks, then turned to the left
+up a cross-street. They went straight ahead, then, until they came to
+the path that led up Cardiff Hill; this they took. They passed by the
+old Welshman's house, half-way up the hill, without hesitating, and
+still climbed upward. Good, thought Huck, they will bury it in the old
+quarry. But they never stopped at the quarry. They passed on, up the
+summit. They plunged into the narrow path between the tall sumach
+bushes, and were at once hidden in the gloom. Huck closed up and
+shortened his distance, now, for they would never be able to see him.
+He trotted along awhile; then slackened his pace, fearing he was
+gaining too fast; moved on a piece, then stopped altogether; listened;
+no sound; none, save that he seemed to hear the beating of his own
+heart. The hooting of an owl came over the hill--ominous sound! But no
+footsteps. Heavens, was everything lost! He was about to spring with
+winged feet, when a man cleared his throat not four feet from him!
+Huck's heart shot into his throat, but he swallowed it again; and then
+he stood there shaking as if a dozen agues had taken charge of him at
+once, and so weak that he thought he must surely fall to the ground. He
+knew where he was. He knew he was within five steps of the stile
+leading into Widow Douglas' grounds. Very well, he thought, let them
+bury it there; it won't be hard to find.
+
+Now there was a voice--a very low voice--Injun Joe's:
+
+"Damn her, maybe she's got company--there's lights, late as it is."
+
+"I can't see any."
+
+This was that stranger's voice--the stranger of the haunted house. A
+deadly chill went to Huck's heart--this, then, was the "revenge" job!
+His thought was, to fly. Then he remembered that the Widow Douglas had
+been kind to him more than once, and maybe these men were going to
+murder her. He wished he dared venture to warn her; but he knew he
+didn't dare--they might come and catch him. He thought all this and
+more in the moment that elapsed between the stranger's remark and Injun
+Joe's next--which was--
+
+"Because the bush is in your way. Now--this way--now you see, don't
+you?"
+
+"Yes. Well, there IS company there, I reckon. Better give it up."
+
+"Give it up, and I just leaving this country forever! Give it up and
+maybe never have another chance. I tell you again, as I've told you
+before, I don't care for her swag--you may have it. But her husband was
+rough on me--many times he was rough on me--and mainly he was the
+justice of the peace that jugged me for a vagrant. And that ain't all.
+It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
+in front of the jail, like a nigger!--with all the town looking on!
+HORSEWHIPPED!--do you understand? He took advantage of me and died. But
+I'll take it out of HER."
+
+"Oh, don't kill her! Don't do that!"
+
+"Kill? Who said anything about killing? I would kill HIM if he was
+here; but not her. When you want to get revenge on a woman you don't
+kill her--bosh! you go for her looks. You slit her nostrils--you notch
+her ears like a sow!"
+
+"By God, that's--"
+
+"Keep your opinion to yourself! It will be safest for you. I'll tie
+her to the bed. If she bleeds to death, is that my fault? I'll not cry,
+if she does. My friend, you'll help me in this thing--for MY sake
+--that's why you're here--I mightn't be able alone. If you flinch, I'll
+kill you. Do you understand that? And if I have to kill you, I'll kill
+her--and then I reckon nobody'll ever know much about who done this
+business."
+
+"Well, if it's got to be done, let's get at it. The quicker the
+better--I'm all in a shiver."
+
+"Do it NOW? And company there? Look here--I'll get suspicious of you,
+first thing you know. No--we'll wait till the lights are out--there's
+no hurry."
+
+Huck felt that a silence was going to ensue--a thing still more awful
+than any amount of murderous talk; so he held his breath and stepped
+gingerly back; planted his foot carefully and firmly, after balancing,
+one-legged, in a precarious way and almost toppling over, first on one
+side and then on the other. He took another step back, with the same
+elaboration and the same risks; then another and another, and--a twig
+snapped under his foot! His breath stopped and he listened. There was
+no sound--the stillness was perfect. His gratitude was measureless. Now
+he turned in his tracks, between the walls of sumach bushes--turned
+himself as carefully as if he were a ship--and then stepped quickly but
+cautiously along. When he emerged at the quarry he felt secure, and so
+he picked up his nimble heels and flew. Down, down he sped, till he
+reached the Welshman's. He banged at the door, and presently the heads
+of the old man and his two stalwart sons were thrust from windows.
+
+"What's the row there? Who's banging? What do you want?"
+
+"Let me in--quick! I'll tell everything."
+
+"Why, who are you?"
+
+"Huckleberry Finn--quick, let me in!"
+
+"Huckleberry Finn, indeed! It ain't a name to open many doors, I
+judge! But let him in, lads, and let's see what's the trouble."
+
+"Please don't ever tell I told you," were Huck's first words when he
+got in. "Please don't--I'd be killed, sure--but the widow's been good
+friends to me sometimes, and I want to tell--I WILL tell if you'll
+promise you won't ever say it was me."
+
+"By George, he HAS got something to tell, or he wouldn't act so!"
+exclaimed the old man; "out with it and nobody here'll ever tell, lad."
+
+Three minutes later the old man and his sons, well armed, were up the
+hill, and just entering the sumach path on tiptoe, their weapons in
+their hands. Huck accompanied them no further. He hid behind a great
+bowlder and fell to listening. There was a lagging, anxious silence,
+and then all of a sudden there was an explosion of firearms and a cry.
+
+Huck waited for no particulars. He sprang away and sped down the hill
+as fast as his legs could carry him.
+
+
+
+CHAPTER XXX
+
+AS the earliest suspicion of dawn appeared on Sunday morning, Huck
+came groping up the hill and rapped gently at the old Welshman's door.
+The inmates were asleep, but it was a sleep that was set on a
+hair-trigger, on account of the exciting episode of the night. A call
+came from a window:
+
+"Who's there!"
+
+Huck's scared voice answered in a low tone:
+
+"Please let me in! It's only Huck Finn!"
+
+"It's a name that can open this door night or day, lad!--and welcome!"
+
+These were strange words to the vagabond boy's ears, and the
+pleasantest he had ever heard. He could not recollect that the closing
+word had ever been applied in his case before. The door was quickly
+unlocked, and he entered. Huck was given a seat and the old man and his
+brace of tall sons speedily dressed themselves.
+
+"Now, my boy, I hope you're good and hungry, because breakfast will be
+ready as soon as the sun's up, and we'll have a piping hot one, too
+--make yourself easy about that! I and the boys hoped you'd turn up and
+stop here last night."
+
+"I was awful scared," said Huck, "and I run. I took out when the
+pistols went off, and I didn't stop for three mile. I've come now becuz
+I wanted to know about it, you know; and I come before daylight becuz I
+didn't want to run across them devils, even if they was dead."
+
+"Well, poor chap, you do look as if you'd had a hard night of it--but
+there's a bed here for you when you've had your breakfast. No, they
+ain't dead, lad--we are sorry enough for that. You see we knew right
+where to put our hands on them, by your description; so we crept along
+on tiptoe till we got within fifteen feet of them--dark as a cellar
+that sumach path was--and just then I found I was going to sneeze. It
+was the meanest kind of luck! I tried to keep it back, but no use
+--'twas bound to come, and it did come! I was in the lead with my pistol
+raised, and when the sneeze started those scoundrels a-rustling to get
+out of the path, I sung out, 'Fire boys!' and blazed away at the place
+where the rustling was. So did the boys. But they were off in a jiffy,
+those villains, and we after them, down through the woods. I judge we
+never touched them. They fired a shot apiece as they started, but their
+bullets whizzed by and didn't do us any harm. As soon as we lost the
+sound of their feet we quit chasing, and went down and stirred up the
+constables. They got a posse together, and went off to guard the river
+bank, and as soon as it is light the sheriff and a gang are going to
+beat up the woods. My boys will be with them presently. I wish we had
+some sort of description of those rascals--'twould help a good deal.
+But you couldn't see what they were like, in the dark, lad, I suppose?"
+
+"Oh yes; I saw them down-town and follered them."
+
+"Splendid! Describe them--describe them, my boy!"
+
+"One's the old deaf and dumb Spaniard that's ben around here once or
+twice, and t'other's a mean-looking, ragged--"
+
+"That's enough, lad, we know the men! Happened on them in the woods
+back of the widow's one day, and they slunk away. Off with you, boys,
+and tell the sheriff--get your breakfast to-morrow morning!"
+
+The Welshman's sons departed at once. As they were leaving the room
+Huck sprang up and exclaimed:
+
+"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
+please!"
+
+"All right if you say it, Huck, but you ought to have the credit of
+what you did."
+
+"Oh no, no! Please don't tell!"
+
+When the young men were gone, the old Welshman said:
+
+"They won't tell--and I won't. But why don't you want it known?"
+
+Huck would not explain, further than to say that he already knew too
+much about one of those men and would not have the man know that he
+knew anything against him for the whole world--he would be killed for
+knowing it, sure.
+
+The old man promised secrecy once more, and said:
+
+"How did you come to follow these fellows, lad? Were they looking
+suspicious?"
+
+Huck was silent while he framed a duly cautious reply. Then he said:
+
+"Well, you see, I'm a kind of a hard lot,--least everybody says so,
+and I don't see nothing agin it--and sometimes I can't sleep much, on
+account of thinking about it and sort of trying to strike out a new way
+of doing. That was the way of it last night. I couldn't sleep, and so I
+come along up-street 'bout midnight, a-turning it all over, and when I
+got to that old shackly brick store by the Temperance Tavern, I backed
+up agin the wall to have another think. Well, just then along comes
+these two chaps slipping along close by me, with something under their
+arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
+wanted a light; so they stopped right before me and the cigars lit up
+their faces and I see that the big one was the deaf and dumb Spaniard,
+by his white whiskers and the patch on his eye, and t'other one was a
+rusty, ragged-looking devil."
+
+"Could you see the rags by the light of the cigars?"
+
+This staggered Huck for a moment. Then he said:
+
+"Well, I don't know--but somehow it seems as if I did."
+
+"Then they went on, and you--"
+
+"Follered 'em--yes. That was it. I wanted to see what was up--they
+sneaked along so. I dogged 'em to the widder's stile, and stood in the
+dark and heard the ragged one beg for the widder, and the Spaniard
+swear he'd spile her looks just as I told you and your two--"
+
+"What! The DEAF AND DUMB man said all that!"
+
+Huck had made another terrible mistake! He was trying his best to keep
+the old man from getting the faintest hint of who the Spaniard might
+be, and yet his tongue seemed determined to get him into trouble in
+spite of all he could do. He made several efforts to creep out of his
+scrape, but the old man's eye was upon him and he made blunder after
+blunder. Presently the Welshman said:
+
+"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
+for all the world. No--I'd protect you--I'd protect you. This Spaniard
+is not deaf and dumb; you've let that slip without intending it; you
+can't cover that up now. You know something about that Spaniard that
+you want to keep dark. Now trust me--tell me what it is, and trust me
+--I won't betray you."
+
+Huck looked into the old man's honest eyes a moment, then bent over
+and whispered in his ear:
+
+"'Tain't a Spaniard--it's Injun Joe!"
+
+The Welshman almost jumped out of his chair. In a moment he said:
+
+"It's all plain enough, now. When you talked about notching ears and
+slitting noses I judged that that was your own embellishment, because
+white men don't take that sort of revenge. But an Injun! That's a
+different matter altogether."
+
+During breakfast the talk went on, and in the course of it the old man
+said that the last thing which he and his sons had done, before going
+to bed, was to get a lantern and examine the stile and its vicinity for
+marks of blood. They found none, but captured a bulky bundle of--
+
+"Of WHAT?"
+
+If the words had been lightning they could not have leaped with a more
+stunning suddenness from Huck's blanched lips. His eyes were staring
+wide, now, and his breath suspended--waiting for the answer. The
+Welshman started--stared in return--three seconds--five seconds--ten
+--then replied:
+
+"Of burglar's tools. Why, what's the MATTER with you?"
+
+Huck sank back, panting gently, but deeply, unutterably grateful. The
+Welshman eyed him gravely, curiously--and presently said:
+
+"Yes, burglar's tools. That appears to relieve you a good deal. But
+what did give you that turn? What were YOU expecting we'd found?"
+
+Huck was in a close place--the inquiring eye was upon him--he would
+have given anything for material for a plausible answer--nothing
+suggested itself--the inquiring eye was boring deeper and deeper--a
+senseless reply offered--there was no time to weigh it, so at a venture
+he uttered it--feebly:
+
+"Sunday-school books, maybe."
+
+Poor Huck was too distressed to smile, but the old man laughed loud
+and joyously, shook up the details of his anatomy from head to foot,
+and ended by saying that such a laugh was money in a-man's pocket,
+because it cut down the doctor's bill like everything. Then he added:
+
+"Poor old chap, you're white and jaded--you ain't well a bit--no
+wonder you're a little flighty and off your balance. But you'll come
+out of it. Rest and sleep will fetch you out all right, I hope."
+
+Huck was irritated to think he had been such a goose and betrayed such
+a suspicious excitement, for he had dropped the idea that the parcel
+brought from the tavern was the treasure, as soon as he had heard the
+talk at the widow's stile. He had only thought it was not the treasure,
+however--he had not known that it wasn't--and so the suggestion of a
+captured bundle was too much for his self-possession. But on the whole
+he felt glad the little episode had happened, for now he knew beyond
+all question that that bundle was not THE bundle, and so his mind was
+at rest and exceedingly comfortable. In fact, everything seemed to be
+drifting just in the right direction, now; the treasure must be still
+in No. 2, the men would be captured and jailed that day, and he and Tom
+could seize the gold that night without any trouble or any fear of
+interruption.
+
+Just as breakfast was completed there was a knock at the door. Huck
+jumped for a hiding-place, for he had no mind to be connected even
+remotely with the late event. The Welshman admitted several ladies and
+gentlemen, among them the Widow Douglas, and noticed that groups of
+citizens were climbing up the hill--to stare at the stile. So the news
+had spread. The Welshman had to tell the story of the night to the
+visitors. The widow's gratitude for her preservation was outspoken.
+
+"Don't say a word about it, madam. There's another that you're more
+beholden to than you are to me and my boys, maybe, but he don't allow
+me to tell his name. We wouldn't have been there but for him."
+
+Of course this excited a curiosity so vast that it almost belittled
+the main matter--but the Welshman allowed it to eat into the vitals of
+his visitors, and through them be transmitted to the whole town, for he
+refused to part with his secret. When all else had been learned, the
+widow said:
+
+"I went to sleep reading in bed and slept straight through all that
+noise. Why didn't you come and wake me?"
+
+"We judged it warn't worth while. Those fellows warn't likely to come
+again--they hadn't any tools left to work with, and what was the use of
+waking you up and scaring you to death? My three negro men stood guard
+at your house all the rest of the night. They've just come back."
+
+More visitors came, and the story had to be told and retold for a
+couple of hours more.
+
+There was no Sabbath-school during day-school vacation, but everybody
+was early at church. The stirring event was well canvassed. News came
+that not a sign of the two villains had been yet discovered. When the
+sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
+Harper as she moved down the aisle with the crowd and said:
+
+"Is my Becky going to sleep all day? I just expected she would be
+tired to death."
+
+"Your Becky?"
+
+"Yes," with a startled look--"didn't she stay with you last night?"
+
+"Why, no."
+
+Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
+talking briskly with a friend, passed by. Aunt Polly said:
+
+"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
+boy that's turned up missing. I reckon my Tom stayed at your house last
+night--one of you. And now he's afraid to come to church. I've got to
+settle with him."
+
+Mrs. Thatcher shook her head feebly and turned paler than ever.
+
+"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
+A marked anxiety came into Aunt Polly's face.
+
+"Joe Harper, have you seen my Tom this morning?"
+
+"No'm."
+
+"When did you see him last?"
+
+Joe tried to remember, but was not sure he could say. The people had
+stopped moving out of church. Whispers passed along, and a boding
+uneasiness took possession of every countenance. Children were
+anxiously questioned, and young teachers. They all said they had not
+noticed whether Tom and Becky were on board the ferryboat on the
+homeward trip; it was dark; no one thought of inquiring if any one was
+missing. One young man finally blurted out his fear that they were
+still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
+crying and wringing her hands.
+
+The alarm swept from lip to lip, from group to group, from street to
+street, and within five minutes the bells were wildly clanging and the
+whole town was up! The Cardiff Hill episode sank into instant
+insignificance, the burglars were forgotten, horses were saddled,
+skiffs were manned, the ferryboat ordered out, and before the horror
+was half an hour old, two hundred men were pouring down highroad and
+river toward the cave.
+
+All the long afternoon the village seemed empty and dead. Many women
+visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
+cried with them, too, and that was still better than words. All the
+tedious night the town waited for news; but when the morning dawned at
+last, all the word that came was, "Send more candles--and send food."
+Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
+sent messages of hope and encouragement from the cave, but they
+conveyed no real cheer.
+
+The old Welshman came home toward daylight, spattered with
+candle-grease, smeared with clay, and almost worn out. He found Huck
+still in the bed that had been provided for him, and delirious with
+fever. The physicians were all at the cave, so the Widow Douglas came
+and took charge of the patient. She said she would do her best by him,
+because, whether he was good, bad, or indifferent, he was the Lord's,
+and nothing that was the Lord's was a thing to be neglected. The
+Welshman said Huck had good spots in him, and the widow said:
+
+"You can depend on it. That's the Lord's mark. He don't leave it off.
+He never does. Puts it somewhere on every creature that comes from his
+hands."
+
+Early in the forenoon parties of jaded men began to straggle into the
+village, but the strongest of the citizens continued searching. All the
+news that could be gained was that remotenesses of the cavern were
+being ransacked that had never been visited before; that every corner
+and crevice was going to be thoroughly searched; that wherever one
+wandered through the maze of passages, lights were to be seen flitting
+hither and thither in the distance, and shoutings and pistol-shots sent
+their hollow reverberations to the ear down the sombre aisles. In one
+place, far from the section usually traversed by tourists, the names
+"BECKY & TOM" had been found traced upon the rocky wall with
+candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
+Thatcher recognized the ribbon and cried over it. She said it was the
+last relic she should ever have of her child; and that no other memorial
+of her could ever be so precious, because this one parted latest from
+the living body before the awful death came. Some said that now and
+then, in the cave, a far-away speck of light would glimmer, and then a
+glorious shout would burst forth and a score of men go trooping down the
+echoing aisle--and then a sickening disappointment always followed; the
+children were not there; it was only a searcher's light.
+
+Three dreadful days and nights dragged their tedious hours along, and
+the village sank into a hopeless stupor. No one had heart for anything.
+The accidental discovery, just made, that the proprietor of the
+Temperance Tavern kept liquor on his premises, scarcely fluttered the
+public pulse, tremendous as the fact was. In a lucid interval, Huck
+feebly led up to the subject of taverns, and finally asked--dimly
+dreading the worst--if anything had been discovered at the Temperance
+Tavern since he had been ill.
+
+"Yes," said the widow.
+
+Huck started up in bed, wild-eyed:
+
+"What? What was it?"
+
+"Liquor!--and the place has been shut up. Lie down, child--what a turn
+you did give me!"
+
+"Only tell me just one thing--only just one--please! Was it Tom Sawyer
+that found it?"
+
+The widow burst into tears. "Hush, hush, child, hush! I've told you
+before, you must NOT talk. You are very, very sick!"
+
+Then nothing but liquor had been found; there would have been a great
+powwow if it had been the gold. So the treasure was gone forever--gone
+forever! But what could she be crying about? Curious that she should
+cry.
+
+These thoughts worked their dim way through Huck's mind, and under the
+weariness they gave him he fell asleep. The widow said to herself:
+
+"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
+could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
+enough, or strength enough, either, to go on searching."
+
+
+
+CHAPTER XXXI
+
+NOW to return to Tom and Becky's share in the picnic. They tripped
+along the murky aisles with the rest of the company, visiting the
+familiar wonders of the cave--wonders dubbed with rather
+over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
+"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
+began, and Tom and Becky engaged in it with zeal until the exertion
+began to grow a trifle wearisome; then they wandered down a sinuous
+avenue holding their candles aloft and reading the tangled web-work of
+names, dates, post-office addresses, and mottoes with which the rocky
+walls had been frescoed (in candle-smoke). Still drifting along and
+talking, they scarcely noticed that they were now in a part of the cave
+whose walls were not frescoed. They smoked their own names under an
+overhanging shelf and moved on. Presently they came to a place where a
+little stream of water, trickling over a ledge and carrying a limestone
+sediment with it, had, in the slow-dragging ages, formed a laced and
+ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
+small body behind it in order to illuminate it for Becky's
+gratification. He found that it curtained a sort of steep natural
+stairway which was enclosed between narrow walls, and at once the
+ambition to be a discoverer seized him. Becky responded to his call,
+and they made a smoke-mark for future guidance, and started upon their
+quest. They wound this way and that, far down into the secret depths of
+the cave, made another mark, and branched off in search of novelties to
+tell the upper world about. In one place they found a spacious cavern,
+from whose ceiling depended a multitude of shining stalactites of the
+length and circumference of a man's leg; they walked all about it,
+wondering and admiring, and presently left it by one of the numerous
+passages that opened into it. This shortly brought them to a bewitching
+spring, whose basin was incrusted with a frostwork of glittering
+crystals; it was in the midst of a cavern whose walls were supported by
+many fantastic pillars which had been formed by the joining of great
+stalactites and stalagmites together, the result of the ceaseless
+water-drip of centuries. Under the roof vast knots of bats had packed
+themselves together, thousands in a bunch; the lights disturbed the
+creatures and they came flocking down by hundreds, squeaking and
+darting furiously at the candles. Tom knew their ways and the danger of
+this sort of conduct. He seized Becky's hand and hurried her into the
+first corridor that offered; and none too soon, for a bat struck
+Becky's light out with its wing while she was passing out of the
+cavern. The bats chased the children a good distance; but the fugitives
+plunged into every new passage that offered, and at last got rid of the
+perilous things. Tom found a subterranean lake, shortly, which
+stretched its dim length away until its shape was lost in the shadows.
+He wanted to explore its borders, but concluded that it would be best
+to sit down and rest awhile, first. Now, for the first time, the deep
+stillness of the place laid a clammy hand upon the spirits of the
+children. Becky said:
+
+"Why, I didn't notice, but it seems ever so long since I heard any of
+the others."
+
+"Come to think, Becky, we are away down below them--and I don't know
+how far away north, or south, or east, or whichever it is. We couldn't
+hear them here."
+
+Becky grew apprehensive.
+
+"I wonder how long we've been down here, Tom? We better start back."
+
+"Yes, I reckon we better. P'raps we better."
+
+"Can you find the way, Tom? It's all a mixed-up crookedness to me."
+
+"I reckon I could find it--but then the bats. If they put our candles
+out it will be an awful fix. Let's try some other way, so as not to go
+through there."
+
+"Well. But I hope we won't get lost. It would be so awful!" and the
+girl shuddered at the thought of the dreadful possibilities.
+
+They started through a corridor, and traversed it in silence a long
+way, glancing at each new opening, to see if there was anything
+familiar about the look of it; but they were all strange. Every time
+Tom made an examination, Becky would watch his face for an encouraging
+sign, and he would say cheerily:
+
+"Oh, it's all right. This ain't the one, but we'll come to it right
+away!"
+
+But he felt less and less hopeful with each failure, and presently
+began to turn off into diverging avenues at sheer random, in desperate
+hope of finding the one that was wanted. He still said it was "all
+right," but there was such a leaden dread at his heart that the words
+had lost their ring and sounded just as if he had said, "All is lost!"
+Becky clung to his side in an anguish of fear, and tried hard to keep
+back the tears, but they would come. At last she said:
+
+"Oh, Tom, never mind the bats, let's go back that way! We seem to get
+worse and worse off all the time."
+
+"Listen!" said he.
+
+Profound silence; silence so deep that even their breathings were
+conspicuous in the hush. Tom shouted. The call went echoing down the
+empty aisles and died out in the distance in a faint sound that
+resembled a ripple of mocking laughter.
+
+"Oh, don't do it again, Tom, it is too horrid," said Becky.
+
+"It is horrid, but I better, Becky; they might hear us, you know," and
+he shouted again.
+
+The "might" was even a chillier horror than the ghostly laughter, it
+so confessed a perishing hope. The children stood still and listened;
+but there was no result. Tom turned upon the back track at once, and
+hurried his steps. It was but a little while before a certain
+indecision in his manner revealed another fearful fact to Becky--he
+could not find his way back!
+
+"Oh, Tom, you didn't make any marks!"
+
+"Becky, I was such a fool! Such a fool! I never thought we might want
+to come back! No--I can't find the way. It's all mixed up."
+
+"Tom, Tom, we're lost! we're lost! We never can get out of this awful
+place! Oh, why DID we ever leave the others!"
+
+She sank to the ground and burst into such a frenzy of crying that Tom
+was appalled with the idea that she might die, or lose her reason. He
+sat down by her and put his arms around her; she buried her face in his
+bosom, she clung to him, she poured out her terrors, her unavailing
+regrets, and the far echoes turned them all to jeering laughter. Tom
+begged her to pluck up hope again, and she said she could not. He fell
+to blaming and abusing himself for getting her into this miserable
+situation; this had a better effect. She said she would try to hope
+again, she would get up and follow wherever he might lead if only he
+would not talk like that any more. For he was no more to blame than
+she, she said.
+
+So they moved on again--aimlessly--simply at random--all they could do
+was to move, keep moving. For a little while, hope made a show of
+reviving--not with any reason to back it, but only because it is its
+nature to revive when the spring has not been taken out of it by age
+and familiarity with failure.
+
+By-and-by Tom took Becky's candle and blew it out. This economy meant
+so much! Words were not needed. Becky understood, and her hope died
+again. She knew that Tom had a whole candle and three or four pieces in
+his pockets--yet he must economize.
+
+By-and-by, fatigue began to assert its claims; the children tried to
+pay attention, for it was dreadful to think of sitting down when time
+was grown to be so precious, moving, in some direction, in any
+direction, was at least progress and might bear fruit; but to sit down
+was to invite death and shorten its pursuit.
+
+At last Becky's frail limbs refused to carry her farther. She sat
+down. Tom rested with her, and they talked of home, and the friends
+there, and the comfortable beds and, above all, the light! Becky cried,
+and Tom tried to think of some way of comforting her, but all his
+encouragements were grown threadbare with use, and sounded like
+sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
+sleep. Tom was grateful. He sat looking into her drawn face and saw it
+grow smooth and natural under the influence of pleasant dreams; and
+by-and-by a smile dawned and rested there. The peaceful face reflected
+somewhat of peace and healing into his own spirit, and his thoughts
+wandered away to bygone times and dreamy memories. While he was deep in
+his musings, Becky woke up with a breezy little laugh--but it was
+stricken dead upon her lips, and a groan followed it.
+
+"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
+don't, Tom! Don't look so! I won't say it again."
+
+"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
+the way out."
+
+"We can try, Tom; but I've seen such a beautiful country in my dream.
+I reckon we are going there."
+
+"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
+
+They rose up and wandered along, hand in hand and hopeless. They tried
+to estimate how long they had been in the cave, but all they knew was
+that it seemed days and weeks, and yet it was plain that this could not
+be, for their candles were not gone yet. A long time after this--they
+could not tell how long--Tom said they must go softly and listen for
+dripping water--they must find a spring. They found one presently, and
+Tom said it was time to rest again. Both were cruelly tired, yet Becky
+said she thought she could go a little farther. She was surprised to
+hear Tom dissent. She could not understand it. They sat down, and Tom
+fastened his candle to the wall in front of them with some clay.
+Thought was soon busy; nothing was said for some time. Then Becky broke
+the silence:
+
+"Tom, I am so hungry!"
+
+Tom took something out of his pocket.
+
+"Do you remember this?" said he.
+
+Becky almost smiled.
+
+"It's our wedding-cake, Tom."
+
+"Yes--I wish it was as big as a barrel, for it's all we've got."
+
+"I saved it from the picnic for us to dream on, Tom, the way grown-up
+people do with wedding-cake--but it'll be our--"
+
+She dropped the sentence where it was. Tom divided the cake and Becky
+ate with good appetite, while Tom nibbled at his moiety. There was
+abundance of cold water to finish the feast with. By-and-by Becky
+suggested that they move on again. Tom was silent a moment. Then he
+said:
+
+"Becky, can you bear it if I tell you something?"
+
+Becky's face paled, but she thought she could.
+
+"Well, then, Becky, we must stay here, where there's water to drink.
+That little piece is our last candle!"
+
+Becky gave loose to tears and wailings. Tom did what he could to
+comfort her, but with little effect. At length Becky said:
+
+"Tom!"
+
+"Well, Becky?"
+
+"They'll miss us and hunt for us!"
+
+"Yes, they will! Certainly they will!"
+
+"Maybe they're hunting for us now, Tom."
+
+"Why, I reckon maybe they are. I hope they are."
+
+"When would they miss us, Tom?"
+
+"When they get back to the boat, I reckon."
+
+"Tom, it might be dark then--would they notice we hadn't come?"
+
+"I don't know. But anyway, your mother would miss you as soon as they
+got home."
+
+A frightened look in Becky's face brought Tom to his senses and he saw
+that he had made a blunder. Becky was not to have gone home that night!
+The children became silent and thoughtful. In a moment a new burst of
+grief from Becky showed Tom that the thing in his mind had struck hers
+also--that the Sabbath morning might be half spent before Mrs. Thatcher
+discovered that Becky was not at Mrs. Harper's.
+
+The children fastened their eyes upon their bit of candle and watched
+it melt slowly and pitilessly away; saw the half inch of wick stand
+alone at last; saw the feeble flame rise and fall, climb the thin
+column of smoke, linger at its top a moment, and then--the horror of
+utter darkness reigned!
+
+How long afterward it was that Becky came to a slow consciousness that
+she was crying in Tom's arms, neither could tell. All that they knew
+was, that after what seemed a mighty stretch of time, both awoke out of
+a dead stupor of sleep and resumed their miseries once more. Tom said
+it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
+but her sorrows were too oppressive, all her hopes were gone. Tom said
+that they must have been missed long ago, and no doubt the search was
+going on. He would shout and maybe some one would come. He tried it;
+but in the darkness the distant echoes sounded so hideously that he
+tried it no more.
+
+The hours wasted away, and hunger came to torment the captives again.
+A portion of Tom's half of the cake was left; they divided and ate it.
+But they seemed hungrier than before. The poor morsel of food only
+whetted desire.
+
+By-and-by Tom said:
+
+"SH! Did you hear that?"
+
+Both held their breath and listened. There was a sound like the
+faintest, far-off shout. Instantly Tom answered it, and leading Becky
+by the hand, started groping down the corridor in its direction.
+Presently he listened again; again the sound was heard, and apparently
+a little nearer.
+
+"It's them!" said Tom; "they're coming! Come along, Becky--we're all
+right now!"
+
+The joy of the prisoners was almost overwhelming. Their speed was
+slow, however, because pitfalls were somewhat common, and had to be
+guarded against. They shortly came to one and had to stop. It might be
+three feet deep, it might be a hundred--there was no passing it at any
+rate. Tom got down on his breast and reached as far down as he could.
+No bottom. They must stay there and wait until the searchers came. They
+listened; evidently the distant shoutings were growing more distant! a
+moment or two more and they had gone altogether. The heart-sinking
+misery of it! Tom whooped until he was hoarse, but it was of no use. He
+talked hopefully to Becky; but an age of anxious waiting passed and no
+sounds came again.
+
+The children groped their way back to the spring. The weary time
+dragged on; they slept again, and awoke famished and woe-stricken. Tom
+believed it must be Tuesday by this time.
+
+Now an idea struck him. There were some side passages near at hand. It
+would be better to explore some of these than bear the weight of the
+heavy time in idleness. He took a kite-line from his pocket, tied it to
+a projection, and he and Becky started, Tom in the lead, unwinding the
+line as he groped along. At the end of twenty steps the corridor ended
+in a "jumping-off place." Tom got down on his knees and felt below, and
+then as far around the corner as he could reach with his hands
+conveniently; he made an effort to stretch yet a little farther to the
+right, and at that moment, not twenty yards away, a human hand, holding
+a candle, appeared from behind a rock! Tom lifted up a glorious shout,
+and instantly that hand was followed by the body it belonged to--Injun
+Joe's! Tom was paralyzed; he could not move. He was vastly gratified
+the next moment, to see the "Spaniard" take to his heels and get
+himself out of sight. Tom wondered that Joe had not recognized his
+voice and come over and killed him for testifying in court. But the
+echoes must have disguised the voice. Without doubt, that was it, he
+reasoned. Tom's fright weakened every muscle in his body. He said to
+himself that if he had strength enough to get back to the spring he
+would stay there, and nothing should tempt him to run the risk of
+meeting Injun Joe again. He was careful to keep from Becky what it was
+he had seen. He told her he had only shouted "for luck."
+
+But hunger and wretchedness rise superior to fears in the long run.
+Another tedious wait at the spring and another long sleep brought
+changes. The children awoke tortured with a raging hunger. Tom believed
+that it must be Wednesday or Thursday or even Friday or Saturday, now,
+and that the search had been given over. He proposed to explore another
+passage. He felt willing to risk Injun Joe and all other terrors. But
+Becky was very weak. She had sunk into a dreary apathy and would not be
+roused. She said she would wait, now, where she was, and die--it would
+not be long. She told Tom to go with the kite-line and explore if he
+chose; but she implored him to come back every little while and speak
+to her; and she made him promise that when the awful time came, he
+would stay by her and hold her hand until all was over.
+
+Tom kissed her, with a choking sensation in his throat, and made a
+show of being confident of finding the searchers or an escape from the
+cave; then he took the kite-line in his hand and went groping down one
+of the passages on his hands and knees, distressed with hunger and sick
+with bodings of coming doom.
+
+
+
+CHAPTER XXXII
+
+TUESDAY afternoon came, and waned to the twilight. The village of St.
+Petersburg still mourned. The lost children had not been found. Public
+prayers had been offered up for them, and many and many a private
+prayer that had the petitioner's whole heart in it; but still no good
+news came from the cave. The majority of the searchers had given up the
+quest and gone back to their daily avocations, saying that it was plain
+the children could never be found. Mrs. Thatcher was very ill, and a
+great part of the time delirious. People said it was heartbreaking to
+hear her call her child, and raise her head and listen a whole minute
+at a time, then lay it wearily down again with a moan. Aunt Polly had
+drooped into a settled melancholy, and her gray hair had grown almost
+white. The village went to its rest on Tuesday night, sad and forlorn.
+
+Away in the middle of the night a wild peal burst from the village
+bells, and in a moment the streets were swarming with frantic half-clad
+people, who shouted, "Turn out! turn out! they're found! they're
+found!" Tin pans and horns were added to the din, the population massed
+itself and moved toward the river, met the children coming in an open
+carriage drawn by shouting citizens, thronged around it, joined its
+homeward march, and swept magnificently up the main street roaring
+huzzah after huzzah!
+
+The village was illuminated; nobody went to bed again; it was the
+greatest night the little town had ever seen. During the first half-hour
+a procession of villagers filed through Judge Thatcher's house, seized
+the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
+speak but couldn't--and drifted out raining tears all over the place.
+
+Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
+would be complete, however, as soon as the messenger dispatched with
+the great news to the cave should get the word to her husband. Tom lay
+upon a sofa with an eager auditory about him and told the history of
+the wonderful adventure, putting in many striking additions to adorn it
+withal; and closed with a description of how he left Becky and went on
+an exploring expedition; how he followed two avenues as far as his
+kite-line would reach; how he followed a third to the fullest stretch of
+the kite-line, and was about to turn back when he glimpsed a far-off
+speck that looked like daylight; dropped the line and groped toward it,
+pushed his head and shoulders through a small hole, and saw the broad
+Mississippi rolling by! And if it had only happened to be night he would
+not have seen that speck of daylight and would not have explored that
+passage any more! He told how he went back for Becky and broke the good
+news and she told him not to fret her with such stuff, for she was
+tired, and knew she was going to die, and wanted to. He described how he
+labored with her and convinced her; and how she almost died for joy when
+she had groped to where she actually saw the blue speck of daylight; how
+he pushed his way out at the hole and then helped her out; how they sat
+there and cried for gladness; how some men came along in a skiff and Tom
+hailed them and told them their situation and their famished condition;
+how the men didn't believe the wild tale at first, "because," said they,
+"you are five miles down the river below the valley the cave is in"
+--then took them aboard, rowed to a house, gave them supper, made them
+rest till two or three hours after dark and then brought them home.
+
+Before day-dawn, Judge Thatcher and the handful of searchers with him
+were tracked out, in the cave, by the twine clews they had strung
+behind them, and informed of the great news.
+
+Three days and nights of toil and hunger in the cave were not to be
+shaken off at once, as Tom and Becky soon discovered. They were
+bedridden all of Wednesday and Thursday, and seemed to grow more and
+more tired and worn, all the time. Tom got about, a little, on
+Thursday, was down-town Friday, and nearly as whole as ever Saturday;
+but Becky did not leave her room until Sunday, and then she looked as
+if she had passed through a wasting illness.
+
+Tom learned of Huck's sickness and went to see him on Friday, but
+could not be admitted to the bedroom; neither could he on Saturday or
+Sunday. He was admitted daily after that, but was warned to keep still
+about his adventure and introduce no exciting topic. The Widow Douglas
+stayed by to see that he obeyed. At home Tom learned of the Cardiff
+Hill event; also that the "ragged man's" body had eventually been found
+in the river near the ferry-landing; he had been drowned while trying
+to escape, perhaps.
+
+About a fortnight after Tom's rescue from the cave, he started off to
+visit Huck, who had grown plenty strong enough, now, to hear exciting
+talk, and Tom had some that would interest him, he thought. Judge
+Thatcher's house was on Tom's way, and he stopped to see Becky. The
+Judge and some friends set Tom to talking, and some one asked him
+ironically if he wouldn't like to go to the cave again. Tom said he
+thought he wouldn't mind it. The Judge said:
+
+"Well, there are others just like you, Tom, I've not the least doubt.
+But we have taken care of that. Nobody will get lost in that cave any
+more."
+
+"Why?"
+
+"Because I had its big door sheathed with boiler iron two weeks ago,
+and triple-locked--and I've got the keys."
+
+Tom turned as white as a sheet.
+
+"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
+
+The water was brought and thrown into Tom's face.
+
+"Ah, now you're all right. What was the matter with you, Tom?"
+
+"Oh, Judge, Injun Joe's in the cave!"
+
+
+
+CHAPTER XXXIII
+
+WITHIN a few minutes the news had spread, and a dozen skiff-loads of
+men were on their way to McDougal's cave, and the ferryboat, well
+filled with passengers, soon followed. Tom Sawyer was in the skiff that
+bore Judge Thatcher.
+
+When the cave door was unlocked, a sorrowful sight presented itself in
+the dim twilight of the place. Injun Joe lay stretched upon the ground,
+dead, with his face close to the crack of the door, as if his longing
+eyes had been fixed, to the latest moment, upon the light and the cheer
+of the free world outside. Tom was touched, for he knew by his own
+experience how this wretch had suffered. His pity was moved, but
+nevertheless he felt an abounding sense of relief and security, now,
+which revealed to him in a degree which he had not fully appreciated
+before how vast a weight of dread had been lying upon him since the day
+he lifted his voice against this bloody-minded outcast.
+
+Injun Joe's bowie-knife lay close by, its blade broken in two. The
+great foundation-beam of the door had been chipped and hacked through,
+with tedious labor; useless labor, too, it was, for the native rock
+formed a sill outside it, and upon that stubborn material the knife had
+wrought no effect; the only damage done was to the knife itself. But if
+there had been no stony obstruction there the labor would have been
+useless still, for if the beam had been wholly cut away Injun Joe could
+not have squeezed his body under the door, and he knew it. So he had
+only hacked that place in order to be doing something--in order to pass
+the weary time--in order to employ his tortured faculties. Ordinarily
+one could find half a dozen bits of candle stuck around in the crevices
+of this vestibule, left there by tourists; but there were none now. The
+prisoner had searched them out and eaten them. He had also contrived to
+catch a few bats, and these, also, he had eaten, leaving only their
+claws. The poor unfortunate had starved to death. In one place, near at
+hand, a stalagmite had been slowly growing up from the ground for ages,
+builded by the water-drip from a stalactite overhead. The captive had
+broken off the stalagmite, and upon the stump had placed a stone,
+wherein he had scooped a shallow hollow to catch the precious drop
+that fell once in every three minutes with the dreary regularity of a
+clock-tick--a dessertspoonful once in four and twenty hours. That drop
+was falling when the Pyramids were new; when Troy fell; when the
+foundations of Rome were laid; when Christ was crucified; when the
+Conqueror created the British empire; when Columbus sailed; when the
+massacre at Lexington was "news." It is falling now; it will still be
+falling when all these things shall have sunk down the afternoon of
+history, and the twilight of tradition, and been swallowed up in the
+thick night of oblivion. Has everything a purpose and a mission? Did
+this drop fall patiently during five thousand years to be ready for
+this flitting human insect's need? and has it another important object
+to accomplish ten thousand years to come? No matter. It is many and
+many a year since the hapless half-breed scooped out the stone to catch
+the priceless drops, but to this day the tourist stares longest at that
+pathetic stone and that slow-dropping water when he comes to see the
+wonders of McDougal's cave. Injun Joe's cup stands first in the list of
+the cavern's marvels; even "Aladdin's Palace" cannot rival it.
+
+Injun Joe was buried near the mouth of the cave; and people flocked
+there in boats and wagons from the towns and from all the farms and
+hamlets for seven miles around; they brought their children, and all
+sorts of provisions, and confessed that they had had almost as
+satisfactory a time at the funeral as they could have had at the
+hanging.
+
+This funeral stopped the further growth of one thing--the petition to
+the governor for Injun Joe's pardon. The petition had been largely
+signed; many tearful and eloquent meetings had been held, and a
+committee of sappy women been appointed to go in deep mourning and wail
+around the governor, and implore him to be a merciful ass and trample
+his duty under foot. Injun Joe was believed to have killed five
+citizens of the village, but what of that? If he had been Satan himself
+there would have been plenty of weaklings ready to scribble their names
+to a pardon-petition, and drip a tear on it from their permanently
+impaired and leaky water-works.
+
+The morning after the funeral Tom took Huck to a private place to have
+an important talk. Huck had learned all about Tom's adventure from the
+Welshman and the Widow Douglas, by this time, but Tom said he reckoned
+there was one thing they had not told him; that thing was what he
+wanted to talk about now. Huck's face saddened. He said:
+
+"I know what it is. You got into No. 2 and never found anything but
+whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
+you, soon as I heard 'bout that whiskey business; and I knowed you
+hadn't got the money becuz you'd 'a' got at me some way or other and
+told me even if you was mum to everybody else. Tom, something's always
+told me we'd never get holt of that swag."
+
+"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
+was all right the Saturday I went to the picnic. Don't you remember you
+was to watch there that night?"
+
+"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
+follered Injun Joe to the widder's."
+
+"YOU followed him?"
+
+"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
+and I don't want 'em souring on me and doing me mean tricks. If it
+hadn't ben for me he'd be down in Texas now, all right."
+
+Then Huck told his entire adventure in confidence to Tom, who had only
+heard of the Welshman's part of it before.
+
+"Well," said Huck, presently, coming back to the main question,
+"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
+--anyways it's a goner for us, Tom."
+
+"Huck, that money wasn't ever in No. 2!"
+
+"What!" Huck searched his comrade's face keenly. "Tom, have you got on
+the track of that money again?"
+
+"Huck, it's in the cave!"
+
+Huck's eyes blazed.
+
+"Say it again, Tom."
+
+"The money's in the cave!"
+
+"Tom--honest injun, now--is it fun, or earnest?"
+
+"Earnest, Huck--just as earnest as ever I was in my life. Will you go
+in there with me and help get it out?"
+
+"I bet I will! I will if it's where we can blaze our way to it and not
+get lost."
+
+"Huck, we can do that without the least little bit of trouble in the
+world."
+
+"Good as wheat! What makes you think the money's--"
+
+"Huck, you just wait till we get in there. If we don't find it I'll
+agree to give you my drum and every thing I've got in the world. I
+will, by jings."
+
+"All right--it's a whiz. When do you say?"
+
+"Right now, if you say it. Are you strong enough?"
+
+"Is it far in the cave? I ben on my pins a little, three or four days,
+now, but I can't walk more'n a mile, Tom--least I don't think I could."
+
+"It's about five mile into there the way anybody but me would go,
+Huck, but there's a mighty short cut that they don't anybody but me
+know about. Huck, I'll take you right to it in a skiff. I'll float the
+skiff down there, and I'll pull it back again all by myself. You
+needn't ever turn your hand over."
+
+"Less start right off, Tom."
+
+"All right. We want some bread and meat, and our pipes, and a little
+bag or two, and two or three kite-strings, and some of these
+new-fangled things they call lucifer matches. I tell you, many's
+the time I wished I had some when I was in there before."
+
+A trifle after noon the boys borrowed a small skiff from a citizen who
+was absent, and got under way at once. When they were several miles
+below "Cave Hollow," Tom said:
+
+"Now you see this bluff here looks all alike all the way down from the
+cave hollow--no houses, no wood-yards, bushes all alike. But do you see
+that white place up yonder where there's been a landslide? Well, that's
+one of my marks. We'll get ashore, now."
+
+They landed.
+
+"Now, Huck, where we're a-standing you could touch that hole I got out
+of with a fishing-pole. See if you can find it."
+
+Huck searched all the place about, and found nothing. Tom proudly
+marched into a thick clump of sumach bushes and said:
+
+"Here you are! Look at it, Huck; it's the snuggest hole in this
+country. You just keep mum about it. All along I've been wanting to be
+a robber, but I knew I'd got to have a thing like this, and where to
+run across it was the bother. We've got it now, and we'll keep it
+quiet, only we'll let Joe Harper and Ben Rogers in--because of course
+there's got to be a Gang, or else there wouldn't be any style about it.
+Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
+
+"Well, it just does, Tom. And who'll we rob?"
+
+"Oh, most anybody. Waylay people--that's mostly the way."
+
+"And kill them?"
+
+"No, not always. Hive them in the cave till they raise a ransom."
+
+"What's a ransom?"
+
+"Money. You make them raise all they can, off'n their friends; and
+after you've kept them a year, if it ain't raised then you kill them.
+That's the general way. Only you don't kill the women. You shut up the
+women, but you don't kill them. They're always beautiful and rich, and
+awfully scared. You take their watches and things, but you always take
+your hat off and talk polite. They ain't anybody as polite as robbers
+--you'll see that in any book. Well, the women get to loving you, and
+after they've been in the cave a week or two weeks they stop crying and
+after that you couldn't get them to leave. If you drove them out they'd
+turn right around and come back. It's so in all the books."
+
+"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
+
+"Yes, it's better in some ways, because it's close to home and
+circuses and all that."
+
+By this time everything was ready and the boys entered the hole, Tom
+in the lead. They toiled their way to the farther end of the tunnel,
+then made their spliced kite-strings fast and moved on. A few steps
+brought them to the spring, and Tom felt a shudder quiver all through
+him. He showed Huck the fragment of candle-wick perched on a lump of
+clay against the wall, and described how he and Becky had watched the
+flame struggle and expire.
+
+The boys began to quiet down to whispers, now, for the stillness and
+gloom of the place oppressed their spirits. They went on, and presently
+entered and followed Tom's other corridor until they reached the
+"jumping-off place." The candles revealed the fact that it was not
+really a precipice, but only a steep clay hill twenty or thirty feet
+high. Tom whispered:
+
+"Now I'll show you something, Huck."
+
+He held his candle aloft and said:
+
+"Look as far around the corner as you can. Do you see that? There--on
+the big rock over yonder--done with candle-smoke."
+
+"Tom, it's a CROSS!"
+
+"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
+where I saw Injun Joe poke up his candle, Huck!"
+
+Huck stared at the mystic sign awhile, and then said with a shaky voice:
+
+"Tom, less git out of here!"
+
+"What! and leave the treasure?"
+
+"Yes--leave it. Injun Joe's ghost is round about there, certain."
+
+"No it ain't, Huck, no it ain't. It would ha'nt the place where he
+died--away out at the mouth of the cave--five mile from here."
+
+"No, Tom, it wouldn't. It would hang round the money. I know the ways
+of ghosts, and so do you."
+
+Tom began to fear that Huck was right. Misgivings gathered in his
+mind. But presently an idea occurred to him--
+
+"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
+ghost ain't a going to come around where there's a cross!"
+
+The point was well taken. It had its effect.
+
+"Tom, I didn't think of that. But that's so. It's luck for us, that
+cross is. I reckon we'll climb down there and have a hunt for that box."
+
+Tom went first, cutting rude steps in the clay hill as he descended.
+Huck followed. Four avenues opened out of the small cavern which the
+great rock stood in. The boys examined three of them with no result.
+They found a small recess in the one nearest the base of the rock, with
+a pallet of blankets spread down in it; also an old suspender, some
+bacon rind, and the well-gnawed bones of two or three fowls. But there
+was no money-box. The lads searched and researched this place, but in
+vain. Tom said:
+
+"He said UNDER the cross. Well, this comes nearest to being under the
+cross. It can't be under the rock itself, because that sets solid on
+the ground."
+
+They searched everywhere once more, and then sat down discouraged.
+Huck could suggest nothing. By-and-by Tom said:
+
+"Lookyhere, Huck, there's footprints and some candle-grease on the
+clay about one side of this rock, but not on the other sides. Now,
+what's that for? I bet you the money IS under the rock. I'm going to
+dig in the clay."
+
+"That ain't no bad notion, Tom!" said Huck with animation.
+
+Tom's "real Barlow" was out at once, and he had not dug four inches
+before he struck wood.
+
+"Hey, Huck!--you hear that?"
+
+Huck began to dig and scratch now. Some boards were soon uncovered and
+removed. They had concealed a natural chasm which led under the rock.
+Tom got into this and held his candle as far under the rock as he
+could, but said he could not see to the end of the rift. He proposed to
+explore. He stooped and passed under; the narrow way descended
+gradually. He followed its winding course, first to the right, then to
+the left, Huck at his heels. Tom turned a short curve, by-and-by, and
+exclaimed:
+
+"My goodness, Huck, lookyhere!"
+
+It was the treasure-box, sure enough, occupying a snug little cavern,
+along with an empty powder-keg, a couple of guns in leather cases, two
+or three pairs of old moccasins, a leather belt, and some other rubbish
+well soaked with the water-drip.
+
+"Got it at last!" said Huck, ploughing among the tarnished coins with
+his hand. "My, but we're rich, Tom!"
+
+"Huck, I always reckoned we'd get it. It's just too good to believe,
+but we HAVE got it, sure! Say--let's not fool around here. Let's snake
+it out. Lemme see if I can lift the box."
+
+It weighed about fifty pounds. Tom could lift it, after an awkward
+fashion, but could not carry it conveniently.
+
+"I thought so," he said; "THEY carried it like it was heavy, that day
+at the ha'nted house. I noticed that. I reckon I was right to think of
+fetching the little bags along."
+
+The money was soon in the bags and the boys took it up to the cross
+rock.
+
+"Now less fetch the guns and things," said Huck.
+
+"No, Huck--leave them there. They're just the tricks to have when we
+go to robbing. We'll keep them there all the time, and we'll hold our
+orgies there, too. It's an awful snug place for orgies."
+
+"What orgies?"
+
+"I dono. But robbers always have orgies, and of course we've got to
+have them, too. Come along, Huck, we've been in here a long time. It's
+getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
+get to the skiff."
+
+They presently emerged into the clump of sumach bushes, looked warily
+out, found the coast clear, and were soon lunching and smoking in the
+skiff. As the sun dipped toward the horizon they pushed out and got
+under way. Tom skimmed up the shore through the long twilight, chatting
+cheerily with Huck, and landed shortly after dark.
+
+"Now, Huck," said Tom, "we'll hide the money in the loft of the
+widow's woodshed, and I'll come up in the morning and we'll count it
+and divide, and then we'll hunt up a place out in the woods for it
+where it will be safe. Just you lay quiet here and watch the stuff till
+I run and hook Benny Taylor's little wagon; I won't be gone a minute."
+
+He disappeared, and presently returned with the wagon, put the two
+small sacks into it, threw some old rags on top of them, and started
+off, dragging his cargo behind him. When the boys reached the
+Welshman's house, they stopped to rest. Just as they were about to move
+on, the Welshman stepped out and said:
+
+"Hallo, who's that?"
+
+"Huck and Tom Sawyer."
+
+"Good! Come along with me, boys, you are keeping everybody waiting.
+Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
+as light as it might be. Got bricks in it?--or old metal?"
+
+"Old metal," said Tom.
+
+"I judged so; the boys in this town will take more trouble and fool
+away more time hunting up six bits' worth of old iron to sell to the
+foundry than they would to make twice the money at regular work. But
+that's human nature--hurry along, hurry along!"
+
+The boys wanted to know what the hurry was about.
+
+"Never mind; you'll see, when we get to the Widow Douglas'."
+
+Huck said with some apprehension--for he was long used to being
+falsely accused:
+
+"Mr. Jones, we haven't been doing nothing."
+
+The Welshman laughed.
+
+"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
+and the widow good friends?"
+
+"Yes. Well, she's ben good friends to me, anyway."
+
+"All right, then. What do you want to be afraid for?"
+
+This question was not entirely answered in Huck's slow mind before he
+found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
+Mr. Jones left the wagon near the door and followed.
+
+The place was grandly lighted, and everybody that was of any
+consequence in the village was there. The Thatchers were there, the
+Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
+and a great many more, and all dressed in their best. The widow
+received the boys as heartily as any one could well receive two such
+looking beings. They were covered with clay and candle-grease. Aunt
+Polly blushed crimson with humiliation, and frowned and shook her head
+at Tom. Nobody suffered half as much as the two boys did, however. Mr.
+Jones said:
+
+"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
+Huck right at my door, and so I just brought them along in a hurry."
+
+"And you did just right," said the widow. "Come with me, boys."
+
+She took them to a bedchamber and said:
+
+"Now wash and dress yourselves. Here are two new suits of clothes
+--shirts, socks, everything complete. They're Huck's--no, no thanks,
+Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
+Get into them. We'll wait--come down when you are slicked up enough."
+
+Then she left.
+
+
+
+CHAPTER XXXIV
+
+HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
+high from the ground."
+
+"Shucks! what do you want to slope for?"
+
+"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
+going down there, Tom."
+
+"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
+of you."
+
+Sid appeared.
+
+"Tom," said he, "auntie has been waiting for you all the afternoon.
+Mary got your Sunday clothes ready, and everybody's been fretting about
+you. Say--ain't this grease and clay, on your clothes?"
+
+"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
+blow-out about, anyway?"
+
+"It's one of the widow's parties that she's always having. This time
+it's for the Welshman and his sons, on account of that scrape they
+helped her out of the other night. And say--I can tell you something,
+if you want to know."
+
+"Well, what?"
+
+"Why, old Mr. Jones is going to try to spring something on the people
+here to-night, but I overheard him tell auntie to-day about it, as a
+secret, but I reckon it's not much of a secret now. Everybody knows
+--the widow, too, for all she tries to let on she don't. Mr. Jones was
+bound Huck should be here--couldn't get along with his grand secret
+without Huck, you know!"
+
+"Secret about what, Sid?"
+
+"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
+was going to make a grand time over his surprise, but I bet you it will
+drop pretty flat."
+
+Sid chuckled in a very contented and satisfied way.
+
+"Sid, was it you that told?"
+
+"Oh, never mind who it was. SOMEBODY told--that's enough."
+
+"Sid, there's only one person in this town mean enough to do that, and
+that's you. If you had been in Huck's place you'd 'a' sneaked down the
+hill and never told anybody on the robbers. You can't do any but mean
+things, and you can't bear to see anybody praised for doing good ones.
+There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
+helped him to the door with several kicks. "Now go and tell auntie if
+you dare--and to-morrow you'll catch it!"
+
+Some minutes later the widow's guests were at the supper-table, and a
+dozen children were propped up at little side-tables in the same room,
+after the fashion of that country and that day. At the proper time Mr.
+Jones made his little speech, in which he thanked the widow for the
+honor she was doing himself and his sons, but said that there was
+another person whose modesty--
+
+And so forth and so on. He sprung his secret about Huck's share in the
+adventure in the finest dramatic manner he was master of, but the
+surprise it occasioned was largely counterfeit and not as clamorous and
+effusive as it might have been under happier circumstances. However,
+the widow made a pretty fair show of astonishment, and heaped so many
+compliments and so much gratitude upon Huck that he almost forgot the
+nearly intolerable discomfort of his new clothes in the entirely
+intolerable discomfort of being set up as a target for everybody's gaze
+and everybody's laudations.
+
+The widow said she meant to give Huck a home under her roof and have
+him educated; and that when she could spare the money she would start
+him in business in a modest way. Tom's chance was come. He said:
+
+"Huck don't need it. Huck's rich."
+
+Nothing but a heavy strain upon the good manners of the company kept
+back the due and proper complimentary laugh at this pleasant joke. But
+the silence was a little awkward. Tom broke it:
+
+"Huck's got money. Maybe you don't believe it, but he's got lots of
+it. Oh, you needn't smile--I reckon I can show you. You just wait a
+minute."
+
+Tom ran out of doors. The company looked at each other with a
+perplexed interest--and inquiringly at Huck, who was tongue-tied.
+
+"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
+making of that boy out. I never--"
+
+Tom entered, struggling with the weight of his sacks, and Aunt Polly
+did not finish her sentence. Tom poured the mass of yellow coin upon
+the table and said:
+
+"There--what did I tell you? Half of it's Huck's and half of it's mine!"
+
+The spectacle took the general breath away. All gazed, nobody spoke
+for a moment. Then there was a unanimous call for an explanation. Tom
+said he could furnish it, and he did. The tale was long, but brimful of
+interest. There was scarcely an interruption from any one to break the
+charm of its flow. When he had finished, Mr. Jones said:
+
+"I thought I had fixed up a little surprise for this occasion, but it
+don't amount to anything now. This one makes it sing mighty small, I'm
+willing to allow."
+
+The money was counted. The sum amounted to a little over twelve
+thousand dollars. It was more than any one present had ever seen at one
+time before, though several persons were there who were worth
+considerably more than that in property.
+
+
+
+CHAPTER XXXV
+
+THE reader may rest satisfied that Tom's and Huck's windfall made a
+mighty stir in the poor little village of St. Petersburg. So vast a
+sum, all in actual cash, seemed next to incredible. It was talked
+about, gloated over, glorified, until the reason of many of the
+citizens tottered under the strain of the unhealthy excitement. Every
+"haunted" house in St. Petersburg and the neighboring villages was
+dissected, plank by plank, and its foundations dug up and ransacked for
+hidden treasure--and not by boys, but men--pretty grave, unromantic
+men, too, some of them. Wherever Tom and Huck appeared they were
+courted, admired, stared at. The boys were not able to remember that
+their remarks had possessed weight before; but now their sayings were
+treasured and repeated; everything they did seemed somehow to be
+regarded as remarkable; they had evidently lost the power of doing and
+saying commonplace things; moreover, their past history was raked up
+and discovered to bear marks of conspicuous originality. The village
+paper published biographical sketches of the boys.
+
+The Widow Douglas put Huck's money out at six per cent., and Judge
+Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
+an income, now, that was simply prodigious--a dollar for every week-day
+in the year and half of the Sundays. It was just what the minister got
+--no, it was what he was promised--he generally couldn't collect it. A
+dollar and a quarter a week would board, lodge, and school a boy in
+those old simple days--and clothe him and wash him, too, for that
+matter.
+
+Judge Thatcher had conceived a great opinion of Tom. He said that no
+commonplace boy would ever have got his daughter out of the cave. When
+Becky told her father, in strict confidence, how Tom had taken her
+whipping at school, the Judge was visibly moved; and when she pleaded
+grace for the mighty lie which Tom had told in order to shift that
+whipping from her shoulders to his own, the Judge said with a fine
+outburst that it was a noble, a generous, a magnanimous lie--a lie that
+was worthy to hold up its head and march down through history breast to
+breast with George Washington's lauded Truth about the hatchet! Becky
+thought her father had never looked so tall and so superb as when he
+walked the floor and stamped his foot and said that. She went straight
+off and told Tom about it.
+
+Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
+day. He said he meant to look to it that Tom should be admitted to the
+National Military Academy and afterward trained in the best law school
+in the country, in order that he might be ready for either career or
+both.
+
+Huck Finn's wealth and the fact that he was now under the Widow
+Douglas' protection introduced him into society--no, dragged him into
+it, hurled him into it--and his sufferings were almost more than he
+could bear. The widow's servants kept him clean and neat, combed and
+brushed, and they bedded him nightly in unsympathetic sheets that had
+not one little spot or stain which he could press to his heart and know
+for a friend. He had to eat with a knife and fork; he had to use
+napkin, cup, and plate; he had to learn his book, he had to go to
+church; he had to talk so properly that speech was become insipid in
+his mouth; whithersoever he turned, the bars and shackles of
+civilization shut him in and bound him hand and foot.
+
+He bravely bore his miseries three weeks, and then one day turned up
+missing. For forty-eight hours the widow hunted for him everywhere in
+great distress. The public were profoundly concerned; they searched
+high and low, they dragged the river for his body. Early the third
+morning Tom Sawyer wisely went poking among some old empty hogsheads
+down behind the abandoned slaughter-house, and in one of them he found
+the refugee. Huck had slept there; he had just breakfasted upon some
+stolen odds and ends of food, and was lying off, now, in comfort, with
+his pipe. He was unkempt, uncombed, and clad in the same old ruin of
+rags that had made him picturesque in the days when he was free and
+happy. Tom routed him out, told him the trouble he had been causing,
+and urged him to go home. Huck's face lost its tranquil content, and
+took a melancholy cast. He said:
+
+"Don't talk about it, Tom. I've tried it, and it don't work; it don't
+work, Tom. It ain't for me; I ain't used to it. The widder's good to
+me, and friendly; but I can't stand them ways. She makes me get up just
+at the same time every morning; she makes me wash, they comb me all to
+thunder; she won't let me sleep in the woodshed; I got to wear them
+blamed clothes that just smothers me, Tom; they don't seem to any air
+git through 'em, somehow; and they're so rotten nice that I can't set
+down, nor lay down, nor roll around anywher's; I hain't slid on a
+cellar-door for--well, it 'pears to be years; I got to go to church and
+sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
+there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
+a bell; she goes to bed by a bell; she gits up by a bell--everything's
+so awful reg'lar a body can't stand it."
+
+"Well, everybody does that way, Huck."
+
+"Tom, it don't make no difference. I ain't everybody, and I can't
+STAND it. It's awful to be tied up so. And grub comes too easy--I don't
+take no interest in vittles, that way. I got to ask to go a-fishing; I
+got to ask to go in a-swimming--dern'd if I hain't got to ask to do
+everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
+to go up in the attic and rip out awhile, every day, to git a taste in
+my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
+wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
+scratch, before folks--" [Then with a spasm of special irritation and
+injury]--"And dad fetch it, she prayed all the time! I never see such a
+woman! I HAD to shove, Tom--I just had to. And besides, that school's
+going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
+Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
+just worry and worry, and sweat and sweat, and a-wishing you was dead
+all the time. Now these clothes suits me, and this bar'l suits me, and
+I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
+all this trouble if it hadn't 'a' ben for that money; now you just take
+my sheer of it along with your'n, and gimme a ten-center sometimes--not
+many times, becuz I don't give a dern for a thing 'thout it's tollable
+hard to git--and you go and beg off for me with the widder."
+
+"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
+you'll try this thing just a while longer you'll come to like it."
+
+"Like it! Yes--the way I'd like a hot stove if I was to set on it long
+enough. No, Tom, I won't be rich, and I won't live in them cussed
+smothery houses. I like the woods, and the river, and hogsheads, and
+I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
+cave, and all just fixed to rob, here this dern foolishness has got to
+come up and spile it all!"
+
+Tom saw his opportunity--
+
+"Lookyhere, Huck, being rich ain't going to keep me back from turning
+robber."
+
+"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
+
+"Just as dead earnest as I'm sitting here. But Huck, we can't let you
+into the gang if you ain't respectable, you know."
+
+Huck's joy was quenched.
+
+"Can't let me in, Tom? Didn't you let me go for a pirate?"
+
+"Yes, but that's different. A robber is more high-toned than what a
+pirate is--as a general thing. In most countries they're awful high up
+in the nobility--dukes and such."
+
+"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
+out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
+
+"Huck, I wouldn't want to, and I DON'T want to--but what would people
+say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
+it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
+
+Huck was silent for some time, engaged in a mental struggle. Finally
+he said:
+
+"Well, I'll go back to the widder for a month and tackle it and see if
+I can come to stand it, if you'll let me b'long to the gang, Tom."
+
+"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
+widow to let up on you a little, Huck."
+
+"Will you, Tom--now will you? That's good. If she'll let up on some of
+the roughest things, I'll smoke private and cuss private, and crowd
+through or bust. When you going to start the gang and turn robbers?"
+
+"Oh, right off. We'll get the boys together and have the initiation
+to-night, maybe."
+
+"Have the which?"
+
+"Have the initiation."
+
+"What's that?"
+
+"It's to swear to stand by one another, and never tell the gang's
+secrets, even if you're chopped all to flinders, and kill anybody and
+all his family that hurts one of the gang."
+
+"That's gay--that's mighty gay, Tom, I tell you."
+
+"Well, I bet it is. And all that swearing's got to be done at
+midnight, in the lonesomest, awfulest place you can find--a ha'nted
+house is the best, but they're all ripped up now."
+
+"Well, midnight's good, anyway, Tom."
+
+"Yes, so it is. And you've got to swear on a coffin, and sign it with
+blood."
+
+"Now, that's something LIKE! Why, it's a million times bullier than
+pirating. I'll stick to the widder till I rot, Tom; and if I git to be
+a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
+she'll be proud she snaked me in out of the wet."
+
+
+
+CONCLUSION
+
+SO endeth this chronicle. It being strictly a history of a BOY, it
+must stop here; the story could not go much further without becoming
+the history of a MAN. When one writes a novel about grown people, he
+knows exactly where to stop--that is, with a marriage; but when he
+writes of juveniles, he must stop where he best can.
+
+Most of the characters that perform in this book still live, and are
+prosperous and happy. Some day it may seem worth while to take up the
+story of the younger ones again and see what sort of men and women they
+turned out to be; therefore it will be wisest not to reveal any of that
+part of their lives at present.
+
+
+
+
+
+End of the Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+*** END OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+***** This file should be named 74.txt or 74.zip *****
+This and all associated files of various formats will be found in:
+ http://www.gutenberg.net/7/74/
+
+Produced by David Widger. The previous edition was update by Jose
+Menendez.
+
+
+Updated editions will replace the previous one--the old editions
+will be renamed.
+
+Creating the works from public domain print editions means that no
+one owns a United States copyright in these works, so the Foundation
+(and you!) can copy and distribute it in the United States without
+permission and without paying copyright royalties. Special rules,
+set forth in the General Terms of Use part of this license, apply to
+copying and distributing Project Gutenberg-tm electronic works to
+protect the PROJECT GUTENBERG-tm concept and trademark. Project
+Gutenberg is a registered trademark, and may not be used if you
+charge for the eBooks, unless you receive specific permission. If you
+do not charge anything for copies of this eBook, complying with the
+rules is very easy. You may use this eBook for nearly any purpose
+such as creation of derivative works, reports, performances and
+research. They may be modified and printed and given away--you may do
+practically ANYTHING with public domain eBooks. Redistribution is
+subject to the trademark license, especially commercial
+redistribution.
+
+
+
+*** START: FULL LICENSE ***
+
+THE FULL PROJECT GUTENBERG LICENSE
+PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
+
+To protect the Project Gutenberg-tm mission of promoting the free
+distribution of electronic works, by using or distributing this work
+(or any other work associated in any way with the phrase "Project
+Gutenberg"), you agree to comply with all the terms of the Full Project
+Gutenberg-tm License (available with this file or online at
+http://gutenberg.net/license).
+
+
+Section 1. General Terms of Use and Redistributing Project Gutenberg-tm
+electronic works
+
+1.A. By reading or using any part of this Project Gutenberg-tm
+electronic work, you indicate that you have read, understand, agree to
+and accept all the terms of this license and intellectual property
+(trademark/copyright) agreement. If you do not agree to abide by all
+the terms of this agreement, you must cease using and return or destroy
+all copies of Project Gutenberg-tm electronic works in your possession.
+If you paid a fee for obtaining a copy of or access to a Project
+Gutenberg-tm electronic work and you do not agree to be bound by the
+terms of this agreement, you may obtain a refund from the person or
+entity to whom you paid the fee as set forth in paragraph 1.E.8.
+
+1.B. "Project Gutenberg" is a registered trademark. It may only be
+used on or associated in any way with an electronic work by people who
+agree to be bound by the terms of this agreement. There are a few
+things that you can do with most Project Gutenberg-tm electronic works
+even without complying with the full terms of this agreement. See
+paragraph 1.C below. There are a lot of things you can do with Project
+Gutenberg-tm electronic works if you follow the terms of this agreement
+and help preserve free future access to Project Gutenberg-tm electronic
+works. See paragraph 1.E below.
+
+1.C. The Project Gutenberg Literary Archive Foundation ("the Foundation"
+or PGLAF), owns a compilation copyright in the collection of Project
+Gutenberg-tm electronic works. Nearly all the individual works in the
+collection are in the public domain in the United States. If an
+individual work is in the public domain in the United States and you are
+located in the United States, we do not claim a right to prevent you from
+copying, distributing, performing, displaying or creating derivative
+works based on the work as long as all references to Project Gutenberg
+are removed. Of course, we hope that you will support the Project
+Gutenberg-tm mission of promoting free access to electronic works by
+freely sharing Project Gutenberg-tm works in compliance with the terms of
+this agreement for keeping the Project Gutenberg-tm name associated with
+the work. You can easily comply with the terms of this agreement by
+keeping this work in the same format with its attached full Project
+Gutenberg-tm License when you share it without charge with others.
+
+1.D. The copyright laws of the place where you are located also govern
+what you can do with this work. Copyright laws in most countries are in
+a constant state of change. If you are outside the United States, check
+the laws of your country in addition to the terms of this agreement
+before downloading, copying, displaying, performing, distributing or
+creating derivative works based on this work or any other Project
+Gutenberg-tm work. The Foundation makes no representations concerning
+the copyright status of any work in any country outside the United
+States.
+
+1.E. Unless you have removed all references to Project Gutenberg:
+
+1.E.1. The following sentence, with active links to, or other immediate
+access to, the full Project Gutenberg-tm License must appear prominently
+whenever any copy of a Project Gutenberg-tm work (any work on which the
+phrase "Project Gutenberg" appears, or with which the phrase "Project
+Gutenberg" is associated) is accessed, displayed, performed, viewed,
+copied or distributed:
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever. You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+1.E.2. If an individual Project Gutenberg-tm electronic work is derived
+from the public domain (does not contain a notice indicating that it is
+posted with permission of the copyright holder), the work can be copied
+and distributed to anyone in the United States without paying any fees
+or charges. If you are redistributing or providing access to a work
+with the phrase "Project Gutenberg" associated with or appearing on the
+work, you must comply either with the requirements of paragraphs 1.E.1
+through 1.E.7 or obtain permission for the use of the work and the
+Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or
+1.E.9.
+
+1.E.3. If an individual Project Gutenberg-tm electronic work is posted
+with the permission of the copyright holder, your use and distribution
+must comply with both paragraphs 1.E.1 through 1.E.7 and any additional
+terms imposed by the copyright holder. Additional terms will be linked
+to the Project Gutenberg-tm License for all works posted with the
+permission of the copyright holder found at the beginning of this work.
+
+1.E.4. Do not unlink or detach or remove the full Project Gutenberg-tm
+License terms from this work, or any files containing a part of this
+work or any other work associated with Project Gutenberg-tm.
+
+1.E.5. Do not copy, display, perform, distribute or redistribute this
+electronic work, or any part of this electronic work, without
+prominently displaying the sentence set forth in paragraph 1.E.1 with
+active links or immediate access to the full terms of the Project
+Gutenberg-tm License.
+
+1.E.6. You may convert to and distribute this work in any binary,
+compressed, marked up, nonproprietary or proprietary form, including any
+word processing or hypertext form. However, if you provide access to or
+distribute copies of a Project Gutenberg-tm work in a format other than
+"Plain Vanilla ASCII" or other format used in the official version
+posted on the official Project Gutenberg-tm web site (www.gutenberg.net),
+you must, at no additional cost, fee or expense to the user, provide a
+copy, a means of exporting a copy, or a means of obtaining a copy upon
+request, of the work in its original "Plain Vanilla ASCII" or other
+form. Any alternate format must include the full Project Gutenberg-tm
+License as specified in paragraph 1.E.1.
+
+1.E.7. Do not charge a fee for access to, viewing, displaying,
+performing, copying or distributing any Project Gutenberg-tm works
+unless you comply with paragraph 1.E.8 or 1.E.9.
+
+1.E.8. You may charge a reasonable fee for copies of or providing
+access to or distributing Project Gutenberg-tm electronic works provided
+that
+
+- You pay a royalty fee of 20% of the gross profits you derive from
+ the use of Project Gutenberg-tm works calculated using the method
+ you already use to calculate your applicable taxes. The fee is
+ owed to the owner of the Project Gutenberg-tm trademark, but he
+ has agreed to donate royalties under this paragraph to the
+ Project Gutenberg Literary Archive Foundation. Royalty payments
+ must be paid within 60 days following each date on which you
+ prepare (or are legally required to prepare) your periodic tax
+ returns. Royalty payments should be clearly marked as such and
+ sent to the Project Gutenberg Literary Archive Foundation at the
+ address specified in Section 4, "Information about donations to
+ the Project Gutenberg Literary Archive Foundation."
+
+- You provide a full refund of any money paid by a user who notifies
+ you in writing (or by e-mail) within 30 days of receipt that s/he
+ does not agree to the terms of the full Project Gutenberg-tm
+ License. You must require such a user to return or
+ destroy all copies of the works possessed in a physical medium
+ and discontinue all use of and all access to other copies of
+ Project Gutenberg-tm works.
+
+- You provide, in accordance with paragraph 1.F.3, a full refund of any
+ money paid for a work or a replacement copy, if a defect in the
+ electronic work is discovered and reported to you within 90 days
+ of receipt of the work.
+
+- You comply with all other terms of this agreement for free
+ distribution of Project Gutenberg-tm works.
+
+1.E.9. If you wish to charge a fee or distribute a Project Gutenberg-tm
+electronic work or group of works on different terms than are set
+forth in this agreement, you must obtain permission in writing from
+both the Project Gutenberg Literary Archive Foundation and Michael
+Hart, the owner of the Project Gutenberg-tm trademark. Contact the
+Foundation as set forth in Section 3 below.
+
+1.F.
+
+1.F.1. Project Gutenberg volunteers and employees expend considerable
+effort to identify, do copyright research on, transcribe and proofread
+public domain works in creating the Project Gutenberg-tm
+collection. Despite these efforts, Project Gutenberg-tm electronic
+works, and the medium on which they may be stored, may contain
+"Defects," such as, but not limited to, incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other intellectual
+property infringement, a defective or damaged disk or other medium, a
+computer virus, or computer codes that damage or cannot be read by
+your equipment.
+
+1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right
+of Replacement or Refund" described in paragraph 1.F.3, the Project
+Gutenberg Literary Archive Foundation, the owner of the Project
+Gutenberg-tm trademark, and any other party distributing a Project
+Gutenberg-tm electronic work under this agreement, disclaim all
+liability to you for damages, costs and expenses, including legal
+fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
+LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
+PROVIDED IN PARAGRAPH F3. YOU AGREE THAT THE FOUNDATION, THE
+TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
+LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
+defect in this electronic work within 90 days of receiving it, you can
+receive a refund of the money (if any) you paid for it by sending a
+written explanation to the person you received the work from. If you
+received the work on a physical medium, you must return the medium with
+your written explanation. The person or entity that provided you with
+the defective work may elect to provide a replacement copy in lieu of a
+refund. If you received the work electronically, the person or entity
+providing it to you may choose to give you a second opportunity to
+receive the work electronically in lieu of a refund. If the second copy
+is also defective, you may demand a refund in writing without further
+opportunities to fix the problem.
+
+1.F.4. Except for the limited right of replacement or refund set forth
+in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.
+
+1.F.5. Some states do not allow disclaimers of certain implied
+warranties or the exclusion or limitation of certain types of damages.
+If any disclaimer or limitation set forth in this agreement violates the
+law of the state applicable to this agreement, the agreement shall be
+interpreted to make the maximum disclaimer or limitation permitted by
+the applicable state law. The invalidity or unenforceability of any
+provision of this agreement shall not void the remaining provisions.
+
+1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the
+trademark owner, any agent or employee of the Foundation, anyone
+providing copies of Project Gutenberg-tm electronic works in accordance
+with this agreement, and any volunteers associated with the production,
+promotion and distribution of Project Gutenberg-tm electronic works,
+harmless from all liability, costs and expenses, including legal fees,
+that arise directly or indirectly from any of the following which you do
+or cause to occur: (a) distribution of this or any Project Gutenberg-tm
+work, (b) alteration, modification, or additions or deletions to any
+Project Gutenberg-tm work, and (c) any Defect you cause.
+
+
+Section 2. Information about the Mission of Project Gutenberg-tm
+
+Project Gutenberg-tm is synonymous with the free distribution of
+electronic works in formats readable by the widest variety of computers
+including obsolete, old, middle-aged and new computers. It exists
+because of the efforts of hundreds of volunteers and donations from
+people in all walks of life.
+
+Volunteers and financial support to provide volunteers with the
+assistance they need, is critical to reaching Project Gutenberg-tm's
+goals and ensuring that the Project Gutenberg-tm collection will
+remain freely available for generations to come. In 2001, the Project
+Gutenberg Literary Archive Foundation was created to provide a secure
+and permanent future for Project Gutenberg-tm and future generations.
+To learn more about the Project Gutenberg Literary Archive Foundation
+and how your efforts and donations can help, see Sections 3 and 4
+and the Foundation web page at http://www.pglaf.org.
+
+
+Section 3. Information about the Project Gutenberg Literary Archive
+Foundation
+
+The Project Gutenberg Literary Archive Foundation is a non profit
+501(c)(3) educational corporation organized under the laws of the
+state of Mississippi and granted tax exempt status by the Internal
+Revenue Service. The Foundation's EIN or federal tax identification
+number is 64-6221541. Its 501(c)(3) letter is posted at
+http://pglaf.org/fundraising. Contributions to the Project Gutenberg
+Literary Archive Foundation are tax deductible to the full extent
+permitted by U.S. federal laws and your state's laws.
+
+The Foundation's principal office is located at 4557 Melan Dr. S.
+Fairbanks, AK, 99712., but its volunteers and employees are scattered
+throughout numerous locations. Its business office is located at
+809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email
+business@pglaf.org. Email contact links and up to date contact
+information can be found at the Foundation's web site and official
+page at http://pglaf.org
+
+For additional contact information:
+ Dr. Gregory B. Newby
+ Chief Executive and Director
+ gbnewby@pglaf.org
+
+
+Section 4. Information about Donations to the Project Gutenberg
+Literary Archive Foundation
+
+Project Gutenberg-tm depends upon and cannot survive without wide
+spread public support and donations to carry out its mission of
+increasing the number of public domain and licensed works that can be
+freely distributed in machine readable form accessible by the widest
+array of equipment including outdated equipment. Many small donations
+($1 to $5,000) are particularly important to maintaining tax exempt
+status with the IRS.
+
+The Foundation is committed to complying with the laws regulating
+charities and charitable donations in all 50 states of the United
+States. Compliance requirements are not uniform and it takes a
+considerable effort, much paperwork and many fees to meet and keep up
+with these requirements. We do not solicit donations in locations
+where we have not received written confirmation of compliance. To
+SEND DONATIONS or determine the status of compliance for any
+particular state visit http://pglaf.org
+
+While we cannot and do not solicit contributions from states where we
+have not met the solicitation requirements, we know of no prohibition
+against accepting unsolicited donations from donors in such states who
+approach us with offers to donate.
+
+International donations are gratefully accepted, but we cannot make
+any statements concerning tax treatment of donations received from
+outside the United States. U.S. laws alone swamp our small staff.
+
+Please check the Project Gutenberg Web pages for current donation
+methods and addresses. Donations are accepted in a number of other
+ways including including checks, online payments and credit card
+donations. To donate, please visit: http://pglaf.org/donate
+
+
+Section 5. General Information About Project Gutenberg-tm electronic
+works.
+
+Professor Michael S. Hart is the originator of the Project Gutenberg-tm
+concept of a library of electronic works that could be freely shared
+with anyone. For thirty years, he produced and distributed Project
+Gutenberg-tm eBooks with only a loose network of volunteer support.
+
+
+Project Gutenberg-tm eBooks are often created from several printed
+editions, all of which are confirmed as Public Domain in the U.S.
+unless a copyright notice is included. Thus, we do not necessarily
+keep eBooks in compliance with any particular paper edition.
+
+
+Most people start at our Web site which has the main PG search facility:
+
+ http://www.gutenberg.net
+
+This Web site includes information about Project Gutenberg-tm,
+including how to make donations to the Project Gutenberg Literary
+Archive Foundation, how to help produce our new eBooks, and how to
+subscribe to our email newsletter to hear about new eBooks.
diff --git a/libgo/go/compress/zlib/reader.go b/libgo/go/compress/zlib/reader.go
index 50a1e6c357f..4638a654842 100644
--- a/libgo/go/compress/zlib/reader.go
+++ b/libgo/go/compress/zlib/reader.go
@@ -34,9 +34,9 @@ import (
const zlibDeflate = 8
-var ChecksumError = errors.New("zlib checksum error")
-var HeaderError = errors.New("invalid zlib header")
-var DictionaryError = errors.New("invalid zlib dictionary")
+var ErrChecksum = errors.New("zlib checksum error")
+var ErrHeader = errors.New("invalid zlib header")
+var ErrDictionary = errors.New("invalid zlib dictionary")
type reader struct {
r flate.Reader
@@ -68,7 +68,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
}
h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
- return nil, HeaderError
+ return nil, ErrHeader
}
if z.scratch[1]&0x20 != 0 {
_, err = io.ReadFull(z.r, z.scratch[0:4])
@@ -77,7 +77,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
}
checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
if checksum != adler32.Checksum(dict) {
- return nil, DictionaryError
+ return nil, ErrDictionary
}
z.decompressor = flate.NewReaderDict(z.r, dict)
} else {
@@ -110,7 +110,7 @@ func (z *reader) Read(p []byte) (n int, err error) {
// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
if checksum != z.digest.Sum32() {
- z.err = ChecksumError
+ z.err = ErrChecksum
return 0, z.err
}
return
diff --git a/libgo/go/compress/zlib/reader_test.go b/libgo/go/compress/zlib/reader_test.go
index d8f9f21478c..3b02a086845 100644
--- a/libgo/go/compress/zlib/reader_test.go
+++ b/libgo/go/compress/zlib/reader_test.go
@@ -45,14 +45,14 @@ var zlibTests = []zlibTest{
"",
[]byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
nil,
- HeaderError,
+ ErrHeader,
},
{
"bad checksum",
"",
[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
nil,
- ChecksumError,
+ ErrChecksum,
},
{
"not enough data",
@@ -95,7 +95,7 @@ var zlibTests = []zlibTest{
[]byte{
0x48, 0x65, 0x6c, 0x6c,
},
- DictionaryError,
+ ErrDictionary,
},
}
diff --git a/libgo/go/crypto/bcrypt/base64.go b/libgo/go/crypto/bcrypt/base64.go
deleted file mode 100644
index fc311609081..00000000000
--- a/libgo/go/crypto/bcrypt/base64.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package bcrypt
-
-import "encoding/base64"
-
-const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-
-var bcEncoding = base64.NewEncoding(alphabet)
-
-func base64Encode(src []byte) []byte {
- n := bcEncoding.EncodedLen(len(src))
- dst := make([]byte, n)
- bcEncoding.Encode(dst, src)
- for dst[n-1] == '=' {
- n--
- }
- return dst[:n]
-}
-
-func base64Decode(src []byte) ([]byte, error) {
- numOfEquals := 4 - (len(src) % 4)
- for i := 0; i < numOfEquals; i++ {
- src = append(src, '=')
- }
-
- dst := make([]byte, bcEncoding.DecodedLen(len(src)))
- n, err := bcEncoding.Decode(dst, src)
- if err != nil {
- return nil, err
- }
- return dst[:n], nil
-}
diff --git a/libgo/go/crypto/bcrypt/bcrypt.go b/libgo/go/crypto/bcrypt/bcrypt.go
deleted file mode 100644
index 362b2eb53cb..00000000000
--- a/libgo/go/crypto/bcrypt/bcrypt.go
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
-// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
-package bcrypt
-
-// The code is a port of Provos and Mazières's C implementation.
-import (
- "crypto/blowfish"
- "crypto/rand"
- "crypto/subtle"
- "errors"
- "fmt"
- "io"
- "strconv"
-)
-
-const (
- MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
- MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
- DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
-)
-
-// The error returned from CompareHashAndPassword when a password and hash do
-// not match.
-var MismatchedHashAndPasswordError = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
-
-// The error returned from CompareHashAndPassword when a hash is too short to
-// be a bcrypt hash.
-var HashTooShortError = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
-
-// The error returned from CompareHashAndPassword when a hash was created with
-// a bcrypt algorithm newer than this implementation.
-type HashVersionTooNewError byte
-
-func (hv HashVersionTooNewError) Error() string {
- return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
-}
-
-// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
-type InvalidHashPrefixError byte
-
-func (ih InvalidHashPrefixError) Error() string {
- return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
-}
-
-type InvalidCostError int
-
-func (ic InvalidCostError) Error() string {
- return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
-}
-
-const (
- majorVersion = '2'
- minorVersion = 'a'
- maxSaltSize = 16
- maxCryptedHashSize = 23
- encodedSaltSize = 22
- encodedHashSize = 31
- minHashSize = 59
-)
-
-// magicCipherData is an IV for the 64 Blowfish encryption calls in
-// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
-var magicCipherData = []byte{
- 0x4f, 0x72, 0x70, 0x68,
- 0x65, 0x61, 0x6e, 0x42,
- 0x65, 0x68, 0x6f, 0x6c,
- 0x64, 0x65, 0x72, 0x53,
- 0x63, 0x72, 0x79, 0x44,
- 0x6f, 0x75, 0x62, 0x74,
-}
-
-type hashed struct {
- hash []byte
- salt []byte
- cost uint32 // allowed range is MinCost to MaxCost
- major byte
- minor byte
-}
-
-// GenerateFromPassword returns the bcrypt hash of the password at the given
-// cost. If the cost given is less than MinCost, the cost will be set to
-// MinCost, instead. Use CompareHashAndPassword, as defined in this package,
-// to compare the returned hashed password with its cleartext version.
-func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
- p, err := newFromPassword(password, cost)
- if err != nil {
- return nil, err
- }
- return p.Hash(), nil
-}
-
-// CompareHashAndPassword compares a bcrypt hashed password with its possible
-// plaintext equivalent. Note: Using bytes.Equal for this job is
-// insecure. Returns nil on success, or an error on failure.
-func CompareHashAndPassword(hashedPassword, password []byte) error {
- p, err := newFromHash(hashedPassword)
- if err != nil {
- return err
- }
-
- otherHash, err := bcrypt(password, p.cost, p.salt)
- if err != nil {
- return err
- }
-
- otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
- if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
- return nil
- }
-
- return MismatchedHashAndPasswordError
-}
-
-func newFromPassword(password []byte, cost int) (*hashed, error) {
- if cost < MinCost {
- cost = DefaultCost
- }
- p := new(hashed)
- p.major = majorVersion
- p.minor = minorVersion
-
- err := checkCost(cost)
- if err != nil {
- return nil, err
- }
- p.cost = uint32(cost)
-
- unencodedSalt := make([]byte, maxSaltSize)
- _, err = io.ReadFull(rand.Reader, unencodedSalt)
- if err != nil {
- return nil, err
- }
-
- p.salt = base64Encode(unencodedSalt)
- hash, err := bcrypt(password, p.cost, p.salt)
- if err != nil {
- return nil, err
- }
- p.hash = hash
- return p, err
-}
-
-func newFromHash(hashedSecret []byte) (*hashed, error) {
- if len(hashedSecret) < minHashSize {
- return nil, HashTooShortError
- }
- p := new(hashed)
- n, err := p.decodeVersion(hashedSecret)
- if err != nil {
- return nil, err
- }
- hashedSecret = hashedSecret[n:]
- n, err = p.decodeCost(hashedSecret)
- if err != nil {
- return nil, err
- }
- hashedSecret = hashedSecret[n:]
-
- // The "+2" is here because we'll have to append at most 2 '=' to the salt
- // when base64 decoding it in expensiveBlowfishSetup().
- p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
- copy(p.salt, hashedSecret[:encodedSaltSize])
-
- hashedSecret = hashedSecret[encodedSaltSize:]
- p.hash = make([]byte, len(hashedSecret))
- copy(p.hash, hashedSecret)
-
- return p, nil
-}
-
-func bcrypt(password []byte, cost uint32, salt []byte) ([]byte, error) {
- cipherData := make([]byte, len(magicCipherData))
- copy(cipherData, magicCipherData)
-
- c, err := expensiveBlowfishSetup(password, cost, salt)
- if err != nil {
- return nil, err
- }
-
- for i := 0; i < 24; i += 8 {
- for j := 0; j < 64; j++ {
- c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
- }
- }
-
- // Bug compatibility with C bcrypt implementations. We only encode 23 of
- // the 24 bytes encrypted.
- hsh := base64Encode(cipherData[:maxCryptedHashSize])
- return hsh, nil
-}
-
-func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
-
- csalt, err := base64Decode(salt)
- if err != nil {
- return nil, err
- }
-
- // Bug compatibility with C bcrypt implementations. They use the trailing
- // NULL in the key string during expansion.
- ckey := append(key, 0)
-
- c, err := blowfish.NewSaltedCipher(ckey, csalt)
- if err != nil {
- return nil, err
- }
-
- rounds := 1 << cost
- for i := 0; i < rounds; i++ {
- blowfish.ExpandKey(ckey, c)
- blowfish.ExpandKey(csalt, c)
- }
-
- return c, nil
-}
-
-func (p *hashed) Hash() []byte {
- arr := make([]byte, 60)
- arr[0] = '$'
- arr[1] = p.major
- n := 2
- if p.minor != 0 {
- arr[2] = p.minor
- n = 3
- }
- arr[n] = '$'
- n += 1
- copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
- n += 2
- arr[n] = '$'
- n += 1
- copy(arr[n:], p.salt)
- n += encodedSaltSize
- copy(arr[n:], p.hash)
- n += encodedHashSize
- return arr[:n]
-}
-
-func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
- if sbytes[0] != '$' {
- return -1, InvalidHashPrefixError(sbytes[0])
- }
- if sbytes[1] > majorVersion {
- return -1, HashVersionTooNewError(sbytes[1])
- }
- p.major = sbytes[1]
- n := 3
- if sbytes[2] != '$' {
- p.minor = sbytes[2]
- n++
- }
- return n, nil
-}
-
-// sbytes should begin where decodeVersion left off.
-func (p *hashed) decodeCost(sbytes []byte) (int, error) {
- cost, err := strconv.Atoi(string(sbytes[0:2]))
- if err != nil {
- return -1, err
- }
- err = checkCost(cost)
- if err != nil {
- return -1, err
- }
- p.cost = uint32(cost)
- return 3, nil
-}
-
-func (p *hashed) String() string {
- return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
-}
-
-func checkCost(cost int) error {
- if cost < MinCost || cost > MaxCost {
- return InvalidCostError(cost)
- }
- return nil
-}
diff --git a/libgo/go/crypto/bcrypt/bcrypt_test.go b/libgo/go/crypto/bcrypt/bcrypt_test.go
deleted file mode 100644
index a3155c5cc72..00000000000
--- a/libgo/go/crypto/bcrypt/bcrypt_test.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package bcrypt
-
-import (
- "bytes"
- "testing"
-)
-
-func TestBcryptingIsEasy(t *testing.T) {
- pass := []byte("mypassword")
- hp, err := GenerateFromPassword(pass, 0)
- if err != nil {
- t.Fatalf("GenerateFromPassword error: %s", err)
- }
-
- if CompareHashAndPassword(hp, pass) != nil {
- t.Errorf("%v should hash %s correctly", hp, pass)
- }
-
- notPass := "notthepass"
- err = CompareHashAndPassword(hp, []byte(notPass))
- if err != MismatchedHashAndPasswordError {
- t.Errorf("%v and %s should be mismatched", hp, notPass)
- }
-}
-
-func TestBcryptingIsCorrect(t *testing.T) {
- pass := []byte("allmine")
- salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
- expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
-
- hash, err := bcrypt(pass, 10, salt)
- if err != nil {
- t.Fatalf("bcrypt blew up: %v", err)
- }
- if !bytes.HasSuffix(expectedHash, hash) {
- t.Errorf("%v should be the suffix of %v", hash, expectedHash)
- }
-
- h, err := newFromHash(expectedHash)
- if err != nil {
- t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
- }
-
- // This is not the safe way to compare these hashes. We do this only for
- // testing clarity. Use bcrypt.CompareHashAndPassword()
- if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
- t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
- }
-}
-
-func TestTooLongPasswordsWork(t *testing.T) {
- salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
- // One byte over the usual 56 byte limit that blowfish has
- tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
- tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
- hash, err := bcrypt(tooLongPass, 10, salt)
- if err != nil {
- t.Fatalf("bcrypt blew up on long password: %v", err)
- }
- if !bytes.HasSuffix(tooLongExpected, hash) {
- t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
- }
-}
-
-type InvalidHashTest struct {
- err error
- hash []byte
-}
-
-var invalidTests = []InvalidHashTest{
- {HashTooShortError, []byte("$2a$10$fooo")},
- {HashTooShortError, []byte("$2a")},
- {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
- {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
- {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-}
-
-func TestInvalidHashErrors(t *testing.T) {
- check := func(name string, expected, err error) {
- if err == nil {
- t.Errorf("%s: Should have returned an error", name)
- }
- if err != nil && err != expected {
- t.Errorf("%s gave err %v but should have given %v", name, err, expected)
- }
- }
- for _, iht := range invalidTests {
- _, err := newFromHash(iht.hash)
- check("newFromHash", iht.err, err)
- err = CompareHashAndPassword(iht.hash, []byte("anything"))
- check("CompareHashAndPassword", iht.err, err)
- }
-}
-
-func TestUnpaddedBase64Encoding(t *testing.T) {
- original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
- encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
-
- encoded := base64Encode(original)
-
- if !bytes.Equal(encodedOriginal, encoded) {
- t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
- }
-
- decoded, err := base64Decode(encodedOriginal)
- if err != nil {
- t.Fatalf("base64Decode blew up: %s", err)
- }
-
- if !bytes.Equal(decoded, original) {
- t.Errorf("Decoded %v should have equaled %v", decoded, original)
- }
-}
-
-func TestCost(t *testing.T) {
- if testing.Short() {
- return
- }
-
- pass := []byte("mypassword")
-
- for c := 0; c < MinCost; c++ {
- p, _ := newFromPassword(pass, c)
- if p.cost != uint32(DefaultCost) {
- t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
- }
- }
-
- p, _ := newFromPassword(pass, 14)
- if p.cost != 14 {
- t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
- }
-
- hp, _ := newFromHash(p.Hash())
- if p.cost != hp.cost {
- t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
- }
-
- _, err := newFromPassword(pass, 32)
- if err == nil {
- t.Fatalf("newFromPassword: should return a cost error")
- }
- if err != InvalidCostError(32) {
- t.Errorf("newFromPassword: should return cost error, got %#v", err)
- }
-}
-
-func TestCostReturnsWithLeadingZeroes(t *testing.T) {
- hp, _ := newFromPassword([]byte("abcdefgh"), 7)
- cost := hp.Hash()[4:7]
- expected := []byte("07$")
-
- if !bytes.Equal(expected, cost) {
- t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
- }
-}
-
-func TestMinorNotRequired(t *testing.T) {
- noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
- h, err := newFromHash(noMinorHash)
- if err != nil {
- t.Fatalf("No minor hash blew up: %s", err)
- }
- if h.minor != 0 {
- t.Errorf("Should leave minor version at 0, but was %d", h.minor)
- }
-
- if !bytes.Equal(noMinorHash, h.Hash()) {
- t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
- }
-}
-
-func BenchmarkEqual(b *testing.B) {
- b.StopTimer()
- passwd := []byte("somepasswordyoulike")
- hash, _ := GenerateFromPassword(passwd, 10)
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- CompareHashAndPassword(hash, passwd)
- }
-}
-
-func BenchmarkGeneration(b *testing.B) {
- b.StopTimer()
- passwd := []byte("mylongpassword1234")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- GenerateFromPassword(passwd, 10)
- }
-}
diff --git a/libgo/go/crypto/blowfish/block.go b/libgo/go/crypto/blowfish/block.go
deleted file mode 100644
index 326292dfc3c..00000000000
--- a/libgo/go/crypto/blowfish/block.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package blowfish
-
-// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
-// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
-// pi and substitution tables for calls to Encrypt. This is used, primarily,
-// by the bcrypt package to reuse the Blowfish key schedule during its
-// set up. It's unlikely that you need to use this directly.
-func ExpandKey(key []byte, c *Cipher) {
- j := 0
- for i := 0; i < 18; i++ {
- var d uint32
- for k := 0; k < 4; k++ {
- d = d<<8 | uint32(key[j])&0x000000FF
- j++
- if j >= len(key) {
- j = 0
- }
- }
- c.p[i] ^= d
- }
-
- var l, r uint32
- for i := 0; i < 18; i += 2 {
- l, r = encryptBlock(l, r, c)
- c.p[i], c.p[i+1] = l, r
- }
-
- for i := 0; i < 256; i += 2 {
- l, r = encryptBlock(l, r, c)
- c.s0[i], c.s0[i+1] = l, r
- }
- for i := 0; i < 256; i += 2 {
- l, r = encryptBlock(l, r, c)
- c.s1[i], c.s1[i+1] = l, r
- }
- for i := 0; i < 256; i += 2 {
- l, r = encryptBlock(l, r, c)
- c.s2[i], c.s2[i+1] = l, r
- }
- for i := 0; i < 256; i += 2 {
- l, r = encryptBlock(l, r, c)
- c.s3[i], c.s3[i+1] = l, r
- }
-}
-
-// This is similar to ExpandKey, but folds the salt during the key
-// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
-// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
-// and specializing it here is useful.
-func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
- j := 0
- expandedKey := make([]uint32, 18)
- for i := 0; i < 18; i++ {
- var d uint32
- for k := 0; k < 4; k++ {
- d = d<<8 | uint32(key[j])&0x000000FF
- j++
- if j >= len(key) {
- j = 0
- }
- }
- expandedKey[i] = d
- c.p[i] ^= d
- }
-
- j = 0
- expandedSalt := make([]uint32, 18)
- for i := 0; i < 18; i++ {
- var d uint32
- for k := 0; k < 4; k++ {
- d = d<<8 | uint32(salt[j])&0x000000FF
- j++
- if j >= len(salt) {
- j = 0
- }
- }
- expandedSalt[i] = d
- }
-
- var l, r uint32
- for i := 0; i < 18; i += 2 {
- l ^= expandedSalt[i&2]
- r ^= expandedSalt[(i&2)+1]
- l, r = encryptBlock(l, r, c)
- c.p[i], c.p[i+1] = l, r
- }
-
- for i := 0; i < 256; i += 4 {
- l ^= expandedSalt[2]
- r ^= expandedSalt[3]
- l, r = encryptBlock(l, r, c)
- c.s0[i], c.s0[i+1] = l, r
-
- l ^= expandedSalt[0]
- r ^= expandedSalt[1]
- l, r = encryptBlock(l, r, c)
- c.s0[i+2], c.s0[i+3] = l, r
-
- }
-
- for i := 0; i < 256; i += 4 {
- l ^= expandedSalt[2]
- r ^= expandedSalt[3]
- l, r = encryptBlock(l, r, c)
- c.s1[i], c.s1[i+1] = l, r
-
- l ^= expandedSalt[0]
- r ^= expandedSalt[1]
- l, r = encryptBlock(l, r, c)
- c.s1[i+2], c.s1[i+3] = l, r
- }
-
- for i := 0; i < 256; i += 4 {
- l ^= expandedSalt[2]
- r ^= expandedSalt[3]
- l, r = encryptBlock(l, r, c)
- c.s2[i], c.s2[i+1] = l, r
-
- l ^= expandedSalt[0]
- r ^= expandedSalt[1]
- l, r = encryptBlock(l, r, c)
- c.s2[i+2], c.s2[i+3] = l, r
- }
-
- for i := 0; i < 256; i += 4 {
- l ^= expandedSalt[2]
- r ^= expandedSalt[3]
- l, r = encryptBlock(l, r, c)
- c.s3[i], c.s3[i+1] = l, r
-
- l ^= expandedSalt[0]
- r ^= expandedSalt[1]
- l, r = encryptBlock(l, r, c)
- c.s3[i+2], c.s3[i+3] = l, r
- }
-}
-
-func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
- xl, xr := l, r
- xl ^= c.p[0]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
- xr ^= c.p[17]
- return xr, xl
-}
-
-func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
- xl, xr := l, r
- xl ^= c.p[17]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
- xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
- xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
- xr ^= c.p[0]
- return xr, xl
-}
-
-func zero(x []uint32) {
- for i := range x {
- x[i] = 0
- }
-}
diff --git a/libgo/go/crypto/blowfish/blowfish_test.go b/libgo/go/crypto/blowfish/blowfish_test.go
deleted file mode 100644
index 1038d2e39ee..00000000000
--- a/libgo/go/crypto/blowfish/blowfish_test.go
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package blowfish
-
-import (
- "testing"
-)
-
-type CryptTest struct {
- key []byte
- in []byte
- out []byte
-}
-
-// Test vector values are from http://www.schneier.com/code/vectors.txt.
-var encryptTests = []CryptTest{
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
- {
- []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
- []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
- []byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
- {
- []byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
- []byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
- {
- []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
- []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
- []byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
-
- {
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
- []byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
- {
- []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
- {
- []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
- {
- []byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
- []byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
- []byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
- {
- []byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
- []byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
- []byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
- {
- []byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
- []byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
- []byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
- {
- []byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
- []byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
- []byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
- {
- []byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
- []byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
- []byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
- {
- []byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
- []byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
- []byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
- {
- []byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
- []byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
- []byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
- {
- []byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
- []byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
- []byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
- {
- []byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
- []byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
- []byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
- {
- []byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
- []byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
- []byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
- {
- []byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
- []byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
- []byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
- {
- []byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
- []byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
- []byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
- {
- []byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
- []byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
- []byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
- {
- []byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
- []byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
- []byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
- {
- []byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
- []byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
- []byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
- {
- []byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
- []byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
- []byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
- {
- []byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
- []byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
- []byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
- {
- []byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
- []byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
- []byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
- {
- []byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
- []byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
- []byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
- {
- []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
- {
- []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
- {
- []byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
- []byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
- {
- []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
- {
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
- {
- []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
- []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
- []byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
-}
-
-func TestCipherEncrypt(t *testing.T) {
- for i, tt := range encryptTests {
- c, err := NewCipher(tt.key)
- if err != nil {
- t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
- continue
- }
- ct := make([]byte, len(tt.out))
- c.Encrypt(ct, tt.in)
- for j, v := range ct {
- if v != tt.out[j] {
- t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
- break
- }
- }
- }
-}
-
-func TestCipherDecrypt(t *testing.T) {
- for i, tt := range encryptTests {
- c, err := NewCipher(tt.key)
- if err != nil {
- t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
- continue
- }
- pt := make([]byte, len(tt.in))
- c.Decrypt(pt, tt.out)
- for j, v := range pt {
- if v != tt.in[j] {
- t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
- break
- }
- }
- }
-}
-
-func TestSaltedCipherKeyLength(t *testing.T) {
- var key []byte
- for i := 0; i < 4; i++ {
- _, err := NewSaltedCipher(key, []byte{'a'})
- if err != KeySizeError(i) {
- t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(i))
- }
- key = append(key, 'a')
- }
-
- // A 57-byte key. One over the typical blowfish restriction.
- key = []byte("012345678901234567890123456789012345678901234567890123456")
- _, err := NewSaltedCipher(key, []byte{'a'})
- if err != nil {
- t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
- }
-}
diff --git a/libgo/go/crypto/blowfish/cipher.go b/libgo/go/crypto/blowfish/cipher.go
deleted file mode 100644
index 94e10f0e267..00000000000
--- a/libgo/go/crypto/blowfish/cipher.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
-package blowfish
-
-// The code is a port of Bruce Schneier's C implementation.
-// See http://www.schneier.com/blowfish.html.
-
-import "strconv"
-
-// The Blowfish block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of Blowfish encryption using a particular key.
-type Cipher struct {
- p [18]uint32
- s0, s1, s2, s3 [256]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
- return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Blowfish key, 4 to 56 bytes.
-func NewCipher(key []byte) (*Cipher, error) {
- var result Cipher
- k := len(key)
- if k < 4 || k > 56 {
- return nil, KeySizeError(k)
- }
- initCipher(key, &result)
- ExpandKey(key, &result)
- return &result, nil
-}
-
-// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
-// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
-// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
-// bytes.
-func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
- var result Cipher
- k := len(key)
- if k < 4 {
- return nil, KeySizeError(k)
- }
- initCipher(key, &result)
- expandKeyWithSalt(key, salt, &result)
- return &result, nil
-}
-
-// BlockSize returns the Blowfish block size, 8 bytes.
-// It is necessary to satisfy the Block interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
- l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
- l, r = encryptBlock(l, r, c)
- dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
- dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Decrypt decrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) {
- l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
- l, r = decryptBlock(l, r, c)
- dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
- dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Reset zeros the key data, so that it will no longer
-// appear in the process's memory.
-func (c *Cipher) Reset() {
- zero(c.p[0:])
- zero(c.s0[0:])
- zero(c.s1[0:])
- zero(c.s2[0:])
- zero(c.s3[0:])
-}
-
-func initCipher(key []byte, c *Cipher) {
- copy(c.p[0:], p[0:])
- copy(c.s0[0:], s0[0:])
- copy(c.s1[0:], s1[0:])
- copy(c.s2[0:], s2[0:])
- copy(c.s3[0:], s3[0:])
-}
diff --git a/libgo/go/crypto/blowfish/const.go b/libgo/go/crypto/blowfish/const.go
deleted file mode 100644
index 8c5ee4cb08a..00000000000
--- a/libgo/go/crypto/blowfish/const.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// The startup permutation array and substitution boxes.
-// They are the hexadecimal digits of PI; see:
-// http://www.schneier.com/code/constants.txt.
-
-package blowfish
-
-var s0 = [256]uint32{
- 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
- 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
- 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
- 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
- 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
- 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
- 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
- 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
- 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
- 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
- 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
- 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
- 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
- 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
- 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
- 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
- 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
- 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
- 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
- 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
- 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
- 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
- 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
- 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
- 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
- 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
- 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
- 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
- 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
- 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
- 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
- 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
- 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
- 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
- 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
- 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
- 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
- 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
- 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
- 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
- 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
- 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
- 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-}
-
-var s1 = [256]uint32{
- 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
- 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
- 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
- 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
- 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
- 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
- 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
- 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
- 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
- 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
- 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
- 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
- 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
- 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
- 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
- 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
- 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
- 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
- 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
- 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
- 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
- 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
- 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
- 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
- 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
- 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
- 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
- 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
- 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
- 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
- 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
- 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
- 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
- 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
- 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
- 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
- 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
- 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
- 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
- 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
- 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
- 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
- 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-}
-
-var s2 = [256]uint32{
- 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
- 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
- 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
- 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
- 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
- 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
- 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
- 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
- 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
- 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
- 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
- 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
- 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
- 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
- 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
- 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
- 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
- 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
- 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
- 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
- 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
- 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
- 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
- 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
- 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
- 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
- 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
- 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
- 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
- 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
- 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
- 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
- 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
- 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
- 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
- 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
- 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
- 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
- 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
- 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
- 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
- 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
- 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-}
-
-var s3 = [256]uint32{
- 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
- 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
- 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
- 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
- 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
- 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
- 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
- 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
- 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
- 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
- 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
- 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
- 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
- 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
- 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
- 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
- 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
- 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
- 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
- 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
- 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
- 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
- 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
- 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
- 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
- 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
- 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
- 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
- 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
- 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
- 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
- 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
- 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
- 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
- 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
- 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
- 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
- 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
- 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
- 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
- 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
- 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
- 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-}
-
-var p = [18]uint32{
- 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
- 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
- 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
-}
diff --git a/libgo/go/crypto/cast5/cast5.go b/libgo/go/crypto/cast5/cast5.go
deleted file mode 100644
index 889a13cb1f7..00000000000
--- a/libgo/go/crypto/cast5/cast5.go
+++ /dev/null
@@ -1,534 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
-// OpenPGP cipher.
-package cast5
-
-import "errors"
-
-const BlockSize = 8
-const KeySize = 16
-
-type Cipher struct {
- masking [16]uint32
- rotate [16]uint8
-}
-
-func NewCipher(key []byte) (c *Cipher, err error) {
- if len(key) != KeySize {
- return nil, errors.New("CAST5: keys must be 16 bytes")
- }
-
- c = new(Cipher)
- c.keySchedule(key)
- return
-}
-
-func (c *Cipher) BlockSize() int {
- return BlockSize
-}
-
-// Reset zeros the key material in memory.
-func (c *Cipher) Reset() {
- for i := 0; i < 16; i++ {
- c.masking[i] = 0
- c.rotate[i] = 0
- }
-}
-
-func (c *Cipher) Encrypt(dst, src []byte) {
- l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-
- l, r = r, l^f1(r, c.masking[0], c.rotate[0])
- l, r = r, l^f2(r, c.masking[1], c.rotate[1])
- l, r = r, l^f3(r, c.masking[2], c.rotate[2])
- l, r = r, l^f1(r, c.masking[3], c.rotate[3])
-
- l, r = r, l^f2(r, c.masking[4], c.rotate[4])
- l, r = r, l^f3(r, c.masking[5], c.rotate[5])
- l, r = r, l^f1(r, c.masking[6], c.rotate[6])
- l, r = r, l^f2(r, c.masking[7], c.rotate[7])
-
- l, r = r, l^f3(r, c.masking[8], c.rotate[8])
- l, r = r, l^f1(r, c.masking[9], c.rotate[9])
- l, r = r, l^f2(r, c.masking[10], c.rotate[10])
- l, r = r, l^f3(r, c.masking[11], c.rotate[11])
-
- l, r = r, l^f1(r, c.masking[12], c.rotate[12])
- l, r = r, l^f2(r, c.masking[13], c.rotate[13])
- l, r = r, l^f3(r, c.masking[14], c.rotate[14])
- l, r = r, l^f1(r, c.masking[15], c.rotate[15])
-
- dst[0] = uint8(r >> 24)
- dst[1] = uint8(r >> 16)
- dst[2] = uint8(r >> 8)
- dst[3] = uint8(r)
- dst[4] = uint8(l >> 24)
- dst[5] = uint8(l >> 16)
- dst[6] = uint8(l >> 8)
- dst[7] = uint8(l)
-}
-
-func (c *Cipher) Decrypt(dst, src []byte) {
- l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-
- l, r = r, l^f1(r, c.masking[15], c.rotate[15])
- l, r = r, l^f3(r, c.masking[14], c.rotate[14])
- l, r = r, l^f2(r, c.masking[13], c.rotate[13])
- l, r = r, l^f1(r, c.masking[12], c.rotate[12])
-
- l, r = r, l^f3(r, c.masking[11], c.rotate[11])
- l, r = r, l^f2(r, c.masking[10], c.rotate[10])
- l, r = r, l^f1(r, c.masking[9], c.rotate[9])
- l, r = r, l^f3(r, c.masking[8], c.rotate[8])
-
- l, r = r, l^f2(r, c.masking[7], c.rotate[7])
- l, r = r, l^f1(r, c.masking[6], c.rotate[6])
- l, r = r, l^f3(r, c.masking[5], c.rotate[5])
- l, r = r, l^f2(r, c.masking[4], c.rotate[4])
-
- l, r = r, l^f1(r, c.masking[3], c.rotate[3])
- l, r = r, l^f3(r, c.masking[2], c.rotate[2])
- l, r = r, l^f2(r, c.masking[1], c.rotate[1])
- l, r = r, l^f1(r, c.masking[0], c.rotate[0])
-
- dst[0] = uint8(r >> 24)
- dst[1] = uint8(r >> 16)
- dst[2] = uint8(r >> 8)
- dst[3] = uint8(r)
- dst[4] = uint8(l >> 24)
- dst[5] = uint8(l >> 16)
- dst[6] = uint8(l >> 8)
- dst[7] = uint8(l)
-}
-
-type keyScheduleA [4][7]uint8
-type keyScheduleB [4][5]uint8
-
-// keyScheduleRound contains the magic values for a round of the key schedule.
-// The keyScheduleA deals with the lines like:
-// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
-// Conceptually, both x and z are in the same array, x first. The first
-// element describes which word of this array gets written to and the
-// second, which word gets read. So, for the line above, it's "4, 0", because
-// it's writing to the first word of z, which, being after x, is word 4, and
-// reading from the first word of x: word 0.
-//
-// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
-// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
-// that it's z that we're indexing.
-//
-// keyScheduleB deals with lines like:
-// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
-// "K1" is ignored because key words are always written in order. So the five
-// elements are the S-box indexes. They use the same form as in keyScheduleA,
-// above.
-
-type keyScheduleRound struct{}
-type keySchedule []keyScheduleRound
-
-var schedule = []struct {
- a keyScheduleA
- b keyScheduleB
-}{
- {
- keyScheduleA{
- {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
- {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
- {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
- {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
- },
- keyScheduleB{
- {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
- {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
- {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
- {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
- },
- },
- {
- keyScheduleA{
- {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
- {1, 4, 0, 2, 1, 3, 16 + 2},
- {2, 5, 7, 6, 5, 4, 16 + 1},
- {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
- },
- keyScheduleB{
- {3, 2, 0xc, 0xd, 8},
- {1, 0, 0xe, 0xf, 0xd},
- {7, 6, 8, 9, 3},
- {5, 4, 0xa, 0xb, 7},
- },
- },
- {
- keyScheduleA{
- {4, 0, 0xd, 0xf, 0xc, 0xe, 8},
- {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
- {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
- {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
- },
- keyScheduleB{
- {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
- {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
- {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
- {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
- },
- },
- {
- keyScheduleA{
- {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
- {1, 4, 0, 2, 1, 3, 16 + 2},
- {2, 5, 7, 6, 5, 4, 16 + 1},
- {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
- },
- keyScheduleB{
- {8, 9, 7, 6, 3},
- {0xa, 0xb, 5, 4, 7},
- {0xc, 0xd, 3, 2, 8},
- {0xe, 0xf, 1, 0, 0xd},
- },
- },
-}
-
-func (c *Cipher) keySchedule(in []byte) {
- var t [8]uint32
- var k [32]uint32
-
- for i := 0; i < 4; i++ {
- j := i * 4
- t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
- }
-
- x := []byte{6, 7, 4, 5}
- ki := 0
-
- for half := 0; half < 2; half++ {
- for _, round := range schedule {
- for j := 0; j < 4; j++ {
- var a [7]uint8
- copy(a[:], round.a[j][:])
- w := t[a[1]]
- w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
- w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
- w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
- w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
- w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
- t[a[0]] = w
- }
-
- for j := 0; j < 4; j++ {
- var b [5]uint8
- copy(b[:], round.b[j][:])
- w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
- w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
- w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
- w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
- w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
- k[ki] = w
- ki++
- }
- }
- }
-
- for i := 0; i < 16; i++ {
- c.masking[i] = k[i]
- c.rotate[i] = uint8(k[16+i] & 0x1f)
- }
-}
-
-// These are the three 'f' functions. See RFC 2144, section 2.2.
-func f1(d, m uint32, r uint8) uint32 {
- t := m + d
- I := (t << r) | (t >> (32 - r))
- return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
-}
-
-func f2(d, m uint32, r uint8) uint32 {
- t := m ^ d
- I := (t << r) | (t >> (32 - r))
- return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
-}
-
-func f3(d, m uint32, r uint8) uint32 {
- t := m - d
- I := (t << r) | (t >> (32 - r))
- return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
-}
-
-var sBox = [8][256]uint32{
- {
- 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
- 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
- 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
- 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
- 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
- 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
- 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
- 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
- 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
- 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
- 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
- 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
- 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
- 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
- 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
- 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
- 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
- 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
- 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
- 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
- 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
- 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
- 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
- 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
- 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
- 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
- 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
- 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
- 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
- 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
- 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
- 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
- },
- {
- 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
- 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
- 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
- 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
- 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
- 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
- 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
- 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
- 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
- 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
- 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
- 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
- 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
- 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
- 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
- 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
- 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
- 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
- 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
- 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
- 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
- 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
- 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
- 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
- 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
- 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
- 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
- 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
- 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
- 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
- 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
- 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
- },
- {
- 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
- 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
- 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
- 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
- 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
- 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
- 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
- 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
- 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
- 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
- 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
- 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
- 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
- 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
- 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
- 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
- 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
- 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
- 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
- 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
- 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
- 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
- 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
- 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
- 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
- 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
- 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
- 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
- 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
- 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
- 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
- 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
- },
- {
- 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
- 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
- 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
- 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
- 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
- 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
- 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
- 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
- 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
- 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
- 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
- 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
- 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
- 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
- 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
- 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
- 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
- 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
- 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
- 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
- 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
- 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
- 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
- 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
- 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
- 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
- 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
- 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
- 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
- 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
- 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
- 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
- },
- {
- 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
- 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
- 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
- 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
- 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
- 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
- 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
- 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
- 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
- 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
- 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
- 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
- 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
- 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
- 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
- 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
- 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
- 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
- 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
- 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
- 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
- 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
- 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
- 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
- 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
- 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
- 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
- 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
- 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
- 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
- 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
- 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
- },
- {
- 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
- 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
- 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
- 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
- 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
- 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
- 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
- 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
- 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
- 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
- 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
- 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
- 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
- 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
- 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
- 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
- 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
- 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
- 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
- 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
- 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
- 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
- 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
- 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
- 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
- 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
- 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
- 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
- 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
- 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
- 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
- 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
- },
- {
- 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
- 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
- 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
- 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
- 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
- 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
- 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
- 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
- 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
- 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
- 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
- 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
- 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
- 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
- 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
- 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
- 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
- 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
- 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
- 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
- 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
- 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
- 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
- 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
- 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
- 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
- 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
- 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
- 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
- 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
- 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
- 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
- },
- {
- 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
- 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
- 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
- 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
- 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
- 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
- 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
- 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
- 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
- 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
- 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
- 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
- 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
- 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
- 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
- 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
- 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
- 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
- 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
- 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
- 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
- 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
- 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
- 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
- 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
- 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
- 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
- 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
- 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
- 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
- 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
- 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
- },
-}
diff --git a/libgo/go/crypto/cast5/cast5_test.go b/libgo/go/crypto/cast5/cast5_test.go
deleted file mode 100644
index 5f7025ff24c..00000000000
--- a/libgo/go/crypto/cast5/cast5_test.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package cast5
-
-import (
- "bytes"
- "encoding/hex"
- "testing"
-)
-
-// This test vector is taken from RFC 2144, App B.1.
-// Since the other two test vectors are for reduced-round variants, we can't
-// use them.
-var basicTests = []struct {
- key, plainText, cipherText string
-}{
- {
- "0123456712345678234567893456789a",
- "0123456789abcdef",
- "238b4fe5847e44b2",
- },
-}
-
-func TestBasic(t *testing.T) {
- for i, test := range basicTests {
- key, _ := hex.DecodeString(test.key)
- plainText, _ := hex.DecodeString(test.plainText)
- expected, _ := hex.DecodeString(test.cipherText)
-
- c, err := NewCipher(key)
- if err != nil {
- t.Errorf("#%d: failed to create Cipher: %s", i, err)
- continue
- }
- var cipherText [BlockSize]byte
- c.Encrypt(cipherText[:], plainText)
- if !bytes.Equal(cipherText[:], expected) {
- t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
- }
-
- var plainTextAgain [BlockSize]byte
- c.Decrypt(plainTextAgain[:], cipherText[:])
- if !bytes.Equal(plainTextAgain[:], plainText) {
- t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
- }
- }
-}
-
-// TestFull performs the test specified in RFC 2144, App B.2.
-// However, due to the length of time taken, it's disabled here and a more
-// limited version is included, below.
-func TestFull(t *testing.T) {
- // This is too slow for normal testing
- return
-
- a, b := iterate(1000000)
-
- const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
- const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
-
- if hex.EncodeToString(a) != expectedA {
- t.Errorf("a: got:%x want:%s", a, expectedA)
- }
- if hex.EncodeToString(b) != expectedB {
- t.Errorf("b: got:%x want:%s", b, expectedB)
- }
-}
-
-func iterate(iterations int) ([]byte, []byte) {
- const initValueHex = "0123456712345678234567893456789a"
-
- initValue, _ := hex.DecodeString(initValueHex)
-
- var a, b [16]byte
- copy(a[:], initValue)
- copy(b[:], initValue)
-
- for i := 0; i < iterations; i++ {
- c, _ := NewCipher(b[:])
- c.Encrypt(a[:8], a[:8])
- c.Encrypt(a[8:], a[8:])
- c, _ = NewCipher(a[:])
- c.Encrypt(b[:8], b[:8])
- c.Encrypt(b[8:], b[8:])
- }
-
- return a[:], b[:]
-}
-
-func TestLimited(t *testing.T) {
- a, b := iterate(1000)
-
- const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
- const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
-
- if hex.EncodeToString(a) != expectedA {
- t.Errorf("a: got:%x want:%s", a, expectedA)
- }
- if hex.EncodeToString(b) != expectedB {
- t.Errorf("b: got:%x want:%s", b, expectedB)
- }
-}
diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go
index be478468455..7aaad1ca199 100644
--- a/libgo/go/crypto/dsa/dsa.go
+++ b/libgo/go/crypto/dsa/dsa.go
@@ -35,11 +35,11 @@ func (invalidPublicKeyError) Error() string {
return "crypto/dsa: invalid public key"
}
-// InvalidPublicKeyError results when a public key is not usable by this code.
+// ErrInvalidPublicKey results when a public key is not usable by this code.
// FIPS is quite strict about the format of DSA keys, but other code may be
// less so. Thus, when using keys which may have been generated by other code,
// this error must be handled.
-var InvalidPublicKeyError = invalidPublicKeyError(0)
+var ErrInvalidPublicKey error = invalidPublicKeyError(0)
// ParameterSizes is a enumeration of the acceptable bit lengths of the primes
// in a set of DSA parameters. See FIPS 186-3, section 4.2.
@@ -194,7 +194,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
n := priv.Q.BitLen()
if n&7 != 0 {
- err = InvalidPublicKeyError
+ err = ErrInvalidPublicKey
return
}
n >>= 3
diff --git a/libgo/go/crypto/md4/md4.go b/libgo/go/crypto/md4/md4.go
deleted file mode 100644
index c5f7c57d16e..00000000000
--- a/libgo/go/crypto/md4/md4.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
-package md4
-
-import (
- "crypto"
- "hash"
-)
-
-func init() {
- crypto.RegisterHash(crypto.MD4, New)
-}
-
-// The size of an MD4 checksum in bytes.
-const Size = 16
-
-// The blocksize of MD4 in bytes.
-const BlockSize = 64
-
-const (
- _Chunk = 64
- _Init0 = 0x67452301
- _Init1 = 0xEFCDAB89
- _Init2 = 0x98BADCFE
- _Init3 = 0x10325476
-)
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
- s [4]uint32
- x [_Chunk]byte
- nx int
- len uint64
-}
-
-func (d *digest) Reset() {
- d.s[0] = _Init0
- d.s[1] = _Init1
- d.s[2] = _Init2
- d.s[3] = _Init3
- d.nx = 0
- d.len = 0
-}
-
-// New returns a new hash.Hash computing the MD4 checksum.
-func New() hash.Hash {
- d := new(digest)
- d.Reset()
- return d
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return BlockSize }
-
-func (d *digest) Write(p []byte) (nn int, err error) {
- nn = len(p)
- d.len += uint64(nn)
- if d.nx > 0 {
- n := len(p)
- if n > _Chunk-d.nx {
- n = _Chunk - d.nx
- }
- for i := 0; i < n; i++ {
- d.x[d.nx+i] = p[i]
- }
- d.nx += n
- if d.nx == _Chunk {
- _Block(d, d.x[0:])
- d.nx = 0
- }
- p = p[n:]
- }
- n := _Block(d, p)
- p = p[n:]
- if len(p) > 0 {
- d.nx = copy(d.x[:], p)
- }
- return
-}
-
-func (d0 *digest) Sum(in []byte) []byte {
- // Make a copy of d0, so that caller can keep writing and summing.
- d := new(digest)
- *d = *d0
-
- // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
- len := d.len
- var tmp [64]byte
- tmp[0] = 0x80
- if len%64 < 56 {
- d.Write(tmp[0 : 56-len%64])
- } else {
- d.Write(tmp[0 : 64+56-len%64])
- }
-
- // Length in bits.
- len <<= 3
- for i := uint(0); i < 8; i++ {
- tmp[i] = byte(len >> (8 * i))
- }
- d.Write(tmp[0:8])
-
- if d.nx != 0 {
- panic("d.nx != 0")
- }
-
- for _, s := range d.s {
- in = append(in, byte(s>>0))
- in = append(in, byte(s>>8))
- in = append(in, byte(s>>16))
- in = append(in, byte(s>>24))
- }
- return in
-}
diff --git a/libgo/go/crypto/md4/md4_test.go b/libgo/go/crypto/md4/md4_test.go
deleted file mode 100644
index b56edd7875d..00000000000
--- a/libgo/go/crypto/md4/md4_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package md4
-
-import (
- "fmt"
- "io"
- "testing"
-)
-
-type md4Test struct {
- out string
- in string
-}
-
-var golden = []md4Test{
- {"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
- {"bde52cb31de33e46245e05fbdbd6fb24", "a"},
- {"ec388dd78999dfc7cf4632465693b6bf", "ab"},
- {"a448017aaf21d8525fc10ae87aa6729d", "abc"},
- {"41decd8f579255c5200f86a4bb3ba740", "abcd"},
- {"9803f4a34e8eb14f96adba49064a0c41", "abcde"},
- {"804e7f1c2586e50b49ac65db5b645131", "abcdef"},
- {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"},
- {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"},
- {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"},
- {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"},
- {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."},
- {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."},
- {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."},
- {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
- {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"},
- {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."},
- {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."},
- {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."},
- {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
- {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
- {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"},
- {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"},
- {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"},
- {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."},
- {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."},
- {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."},
- {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"},
- {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
- {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"},
- {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"},
-}
-
-func TestGolden(t *testing.T) {
- for i := 0; i < len(golden); i++ {
- g := golden[i]
- c := New()
- for j := 0; j < 3; j++ {
- if j < 2 {
- io.WriteString(c, g.in)
- } else {
- io.WriteString(c, g.in[0:len(g.in)/2])
- c.Sum(nil)
- io.WriteString(c, g.in[len(g.in)/2:])
- }
- s := fmt.Sprintf("%x", c.Sum(nil))
- if s != g.out {
- t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out)
- }
- c.Reset()
- }
- }
-}
diff --git a/libgo/go/crypto/md4/md4block.go b/libgo/go/crypto/md4/md4block.go
deleted file mode 100644
index 3fed475f3f6..00000000000
--- a/libgo/go/crypto/md4/md4block.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MD4 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-package md4
-
-var shift1 = []uint{3, 7, 11, 19}
-var shift2 = []uint{3, 5, 9, 13}
-var shift3 = []uint{3, 9, 11, 15}
-
-var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}
-var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}
-
-func _Block(dig *digest, p []byte) int {
- a := dig.s[0]
- b := dig.s[1]
- c := dig.s[2]
- d := dig.s[3]
- n := 0
- var X [16]uint32
- for len(p) >= _Chunk {
- aa, bb, cc, dd := a, b, c, d
-
- j := 0
- for i := 0; i < 16; i++ {
- X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
- j += 4
- }
-
- // If this needs to be made faster in the future,
- // the usual trick is to unroll each of these
- // loops by a factor of 4; that lets you replace
- // the shift[] lookups with constants and,
- // with suitable variable renaming in each
- // unrolled body, delete the a, b, c, d = d, a, b, c
- // (or you can let the optimizer do the renaming).
- //
- // The index variables are uint so that % by a power
- // of two can be optimized easily by a compiler.
-
- // Round 1.
- for i := uint(0); i < 16; i++ {
- x := i
- s := shift1[i%4]
- f := ((c ^ d) & b) ^ d
- a += f + X[x]
- a = a<<s | a>>(32-s)
- a, b, c, d = d, a, b, c
- }
-
- // Round 2.
- for i := uint(0); i < 16; i++ {
- x := xIndex2[i]
- s := shift2[i%4]
- g := (b & c) | (b & d) | (c & d)
- a += g + X[x] + 0x5a827999
- a = a<<s | a>>(32-s)
- a, b, c, d = d, a, b, c
- }
-
- // Round 3.
- for i := uint(0); i < 16; i++ {
- x := xIndex3[i]
- s := shift3[i%4]
- h := b ^ c ^ d
- a += h + X[x] + 0x6ed9eba1
- a = a<<s | a>>(32-s)
- a, b, c, d = d, a, b, c
- }
-
- a += aa
- b += bb
- c += cc
- d += dd
-
- p = p[_Chunk:]
- n += _Chunk
- }
-
- dig.s[0] = a
- dig.s[1] = b
- dig.s[2] = c
- dig.s[3] = d
- return n
-}
diff --git a/libgo/go/crypto/ocsp/ocsp.go b/libgo/go/crypto/ocsp/ocsp.go
deleted file mode 100644
index b9dfdf94e31..00000000000
--- a/libgo/go/crypto/ocsp/ocsp.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
-// are signed messages attesting to the validity of a certificate for a small
-// period of time. This is used to manage revocation for X.509 certificates.
-package ocsp
-
-import (
- "crypto"
- "crypto/rsa"
- _ "crypto/sha1"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/asn1"
- "time"
-)
-
-var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
-var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5})
-
-// These are internal structures that reflect the ASN.1 structure of an OCSP
-// response. See RFC 2560, section 4.2.
-
-const (
- ocspSuccess = 0
- ocspMalformed = 1
- ocspInternalError = 2
- ocspTryLater = 3
- ocspSigRequired = 4
- ocspUnauthorized = 5
-)
-
-type certID struct {
- HashAlgorithm pkix.AlgorithmIdentifier
- NameHash []byte
- IssuerKeyHash []byte
- SerialNumber asn1.RawValue
-}
-
-type responseASN1 struct {
- Status asn1.Enumerated
- Response responseBytes `asn1:"explicit,tag:0"`
-}
-
-type responseBytes struct {
- ResponseType asn1.ObjectIdentifier
- Response []byte
-}
-
-type basicResponse struct {
- TBSResponseData responseData
- SignatureAlgorithm pkix.AlgorithmIdentifier
- Signature asn1.BitString
- Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"`
-}
-
-type responseData struct {
- Raw asn1.RawContent
- Version int `asn1:"optional,default:1,explicit,tag:0"`
- RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
- KeyHash []byte `asn1:"optional,explicit,tag:2"`
- ProducedAt time.Time
- Responses []singleResponse
-}
-
-type singleResponse struct {
- CertID certID
- Good asn1.Flag `asn1:"explicit,tag:0,optional"`
- Revoked revokedInfo `asn1:"explicit,tag:1,optional"`
- Unknown asn1.Flag `asn1:"explicit,tag:2,optional"`
- ThisUpdate time.Time
- NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
-}
-
-type revokedInfo struct {
- RevocationTime time.Time
- Reason int `asn1:"explicit,tag:0,optional"`
-}
-
-// This is the exposed reflection of the internal OCSP structures.
-
-const (
- // Good means that the certificate is valid.
- Good = iota
- // Revoked means that the certificate has been deliberately revoked.
- Revoked = iota
- // Unknown means that the OCSP responder doesn't know about the certificate.
- Unknown = iota
- // ServerFailed means that the OCSP responder failed to process the request.
- ServerFailed = iota
-)
-
-// Response represents an OCSP response. See RFC 2560.
-type Response struct {
- // Status is one of {Good, Revoked, Unknown, ServerFailed}
- Status int
- SerialNumber []byte
- ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
- RevocationReason int
- Certificate *x509.Certificate
-}
-
-// ParseError results from an invalid OCSP response.
-type ParseError string
-
-func (p ParseError) Error() string {
- return string(p)
-}
-
-// ParseResponse parses an OCSP response in DER form. It only supports
-// responses for a single certificate and only those using RSA signatures.
-// Non-RSA responses will result in an x509.UnsupportedAlgorithmError.
-// Signature errors or parse failures will result in a ParseError.
-func ParseResponse(bytes []byte) (*Response, error) {
- var resp responseASN1
- rest, err := asn1.Unmarshal(bytes, &resp)
- if err != nil {
- return nil, err
- }
- if len(rest) > 0 {
- return nil, ParseError("trailing data in OCSP response")
- }
-
- ret := new(Response)
- if resp.Status != ocspSuccess {
- ret.Status = ServerFailed
- return ret, nil
- }
-
- if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
- return nil, ParseError("bad OCSP response type")
- }
-
- var basicResp basicResponse
- rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
- if err != nil {
- return nil, err
- }
-
- if len(basicResp.Certificates) != 1 {
- return nil, ParseError("OCSP response contains bad number of certificates")
- }
-
- if len(basicResp.TBSResponseData.Responses) != 1 {
- return nil, ParseError("OCSP response contains bad number of responses")
- }
-
- ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
- if err != nil {
- return nil, err
- }
-
- if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) {
- return nil, x509.UnsupportedAlgorithmError{}
- }
-
- hashType := crypto.SHA1
- h := hashType.New()
-
- pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
- h.Write(basicResp.TBSResponseData.Raw)
- digest := h.Sum(nil)
- signature := basicResp.Signature.RightAlign()
-
- if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil {
- return nil, ParseError("bad OCSP signature")
- }
-
- r := basicResp.TBSResponseData.Responses[0]
-
- ret.SerialNumber = r.CertID.SerialNumber.Bytes
-
- switch {
- case bool(r.Good):
- ret.Status = Good
- case bool(r.Unknown):
- ret.Status = Unknown
- default:
- ret.Status = Revoked
- ret.RevokedAt = r.Revoked.RevocationTime
- ret.RevocationReason = r.Revoked.Reason
- }
-
- ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
- ret.ThisUpdate = r.ThisUpdate
- ret.NextUpdate = r.NextUpdate
-
- return ret, nil
-}
diff --git a/libgo/go/crypto/ocsp/ocsp_test.go b/libgo/go/crypto/ocsp/ocsp_test.go
deleted file mode 100644
index f0e9f94ee7f..00000000000
--- a/libgo/go/crypto/ocsp/ocsp_test.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ocsp
-
-import (
- "bytes"
- "encoding/hex"
- "reflect"
- "testing"
- "time"
-)
-
-func TestOCSPDecode(t *testing.T) {
- responseBytes, _ := hex.DecodeString(ocspResponseHex)
- resp, err := ParseResponse(responseBytes)
- if err != nil {
- t.Error(err)
- }
-
- expected := Response{
- Status: 0,
- SerialNumber: []byte{0x1, 0xd0, 0xfa},
- RevocationReason: 0,
- ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
- NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
- }
-
- if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
- t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
- }
-
- if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
- t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
- }
-
- if resp.Status != expected.Status {
- t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
- }
-
- if !bytes.Equal(resp.SerialNumber, expected.SerialNumber) {
- t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
- }
-
- if resp.RevocationReason != expected.RevocationReason {
- t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason)
- }
-}
-
-// This OCSP response was taken from Thawte's public OCSP responder.
-// To recreate:
-// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
-// Copy and paste the first certificate into /tmp/cert.crt and the second into
-// /tmp/intermediate.crt
-// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der
-// Then hex encode the result:
-// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")'
-
-const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" +
- "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" +
- "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" +
- "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" +
- "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" +
- "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" +
- "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" +
- "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" +
- "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" +
- "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" +
- "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" +
- "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" +
- "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" +
- "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" +
- "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" +
- "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" +
- "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" +
- "69676974616c204365727469666963617465205369676e696e6731383036060355040313" +
- "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" +
- "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" +
- "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" +
- "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" +
- "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" +
- "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" +
- "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" +
- "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" +
- "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" +
- "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" +
- "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" +
- "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" +
- "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" +
- "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" +
- "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" +
- "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" +
- "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" +
- "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" +
- "4469676974616c204365727469666963617465205369676e696e67312930270603550403" +
- "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" +
- "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" +
- "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" +
- "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" +
- "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" +
- "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" +
- "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" +
- "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" +
- "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
- "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
- "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
diff --git a/libgo/go/crypto/openpgp/armor/armor.go b/libgo/go/crypto/openpgp/armor/armor.go
deleted file mode 100644
index 96957ab1b48..00000000000
--- a/libgo/go/crypto/openpgp/armor/armor.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
-// very similar to PEM except that it has an additional CRC checksum.
-package armor
-
-import (
- "bufio"
- "bytes"
- "crypto/openpgp/errors"
- "encoding/base64"
- "io"
-)
-
-// A Block represents an OpenPGP armored structure.
-//
-// The encoded form is:
-// -----BEGIN Type-----
-// Headers
-//
-// base64-encoded Bytes
-// '=' base64 encoded checksum
-// -----END Type-----
-// where Headers is a possibly empty sequence of Key: Value lines.
-//
-// Since the armored data can be very large, this package presents a streaming
-// interface.
-type Block struct {
- Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
- Header map[string]string // Optional headers.
- Body io.Reader // A Reader from which the contents can be read
- lReader lineReader
- oReader openpgpReader
-}
-
-var ArmorCorrupt error = errors.StructuralError("armor invalid")
-
-const crc24Init = 0xb704ce
-const crc24Poly = 0x1864cfb
-const crc24Mask = 0xffffff
-
-// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
-func crc24(crc uint32, d []byte) uint32 {
- for _, b := range d {
- crc ^= uint32(b) << 16
- for i := 0; i < 8; i++ {
- crc <<= 1
- if crc&0x1000000 != 0 {
- crc ^= crc24Poly
- }
- }
- }
- return crc
-}
-
-var armorStart = []byte("-----BEGIN ")
-var armorEnd = []byte("-----END ")
-var armorEndOfLine = []byte("-----")
-
-// lineReader wraps a line based reader. It watches for the end of an armor
-// block and records the expected CRC value.
-type lineReader struct {
- in *bufio.Reader
- buf []byte
- eof bool
- crc uint32
-}
-
-func (l *lineReader) Read(p []byte) (n int, err error) {
- if l.eof {
- return 0, io.EOF
- }
-
- if len(l.buf) > 0 {
- n = copy(p, l.buf)
- l.buf = l.buf[n:]
- return
- }
-
- line, isPrefix, err := l.in.ReadLine()
- if err != nil {
- return
- }
- if isPrefix {
- return 0, ArmorCorrupt
- }
-
- if len(line) == 5 && line[0] == '=' {
- // This is the checksum line
- var expectedBytes [3]byte
- var m int
- m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
- if m != 3 || err != nil {
- return
- }
- l.crc = uint32(expectedBytes[0])<<16 |
- uint32(expectedBytes[1])<<8 |
- uint32(expectedBytes[2])
-
- line, _, err = l.in.ReadLine()
- if err != nil && err != io.EOF {
- return
- }
- if !bytes.HasPrefix(line, armorEnd) {
- return 0, ArmorCorrupt
- }
-
- l.eof = true
- return 0, io.EOF
- }
-
- if len(line) > 64 {
- return 0, ArmorCorrupt
- }
-
- n = copy(p, line)
- bytesToSave := len(line) - n
- if bytesToSave > 0 {
- if cap(l.buf) < bytesToSave {
- l.buf = make([]byte, 0, bytesToSave)
- }
- l.buf = l.buf[0:bytesToSave]
- copy(l.buf, line[n:])
- }
-
- return
-}
-
-// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
-// a running CRC of the resulting data and checks the CRC against the value
-// found by the lineReader at EOF.
-type openpgpReader struct {
- lReader *lineReader
- b64Reader io.Reader
- currentCRC uint32
-}
-
-func (r *openpgpReader) Read(p []byte) (n int, err error) {
- n, err = r.b64Reader.Read(p)
- r.currentCRC = crc24(r.currentCRC, p[:n])
-
- if err == io.EOF {
- if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
- return 0, ArmorCorrupt
- }
- }
-
- return
-}
-
-// Decode reads a PGP armored block from the given Reader. It will ignore
-// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
-// given Reader is not usable after calling this function: an arbitrary amount
-// of data may have been read past the end of the block.
-func Decode(in io.Reader) (p *Block, err error) {
- r, _ := bufio.NewReaderSize(in, 100)
- var line []byte
- ignoreNext := false
-
-TryNextBlock:
- p = nil
-
- // Skip leading garbage
- for {
- ignoreThis := ignoreNext
- line, ignoreNext, err = r.ReadLine()
- if err != nil {
- return
- }
- if ignoreNext || ignoreThis {
- continue
- }
- line = bytes.TrimSpace(line)
- if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
- break
- }
- }
-
- p = new(Block)
- p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
- p.Header = make(map[string]string)
- nextIsContinuation := false
- var lastKey string
-
- // Read headers
- for {
- isContinuation := nextIsContinuation
- line, nextIsContinuation, err = r.ReadLine()
- if err != nil {
- p = nil
- return
- }
- if isContinuation {
- p.Header[lastKey] += string(line)
- continue
- }
- line = bytes.TrimSpace(line)
- if len(line) == 0 {
- break
- }
-
- i := bytes.Index(line, []byte(": "))
- if i == -1 {
- goto TryNextBlock
- }
- lastKey = string(line[:i])
- p.Header[lastKey] = string(line[i+2:])
- }
-
- p.lReader.in = r
- p.oReader.currentCRC = crc24Init
- p.oReader.lReader = &p.lReader
- p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
- p.Body = &p.oReader
-
- return
-}
diff --git a/libgo/go/crypto/openpgp/armor/armor_test.go b/libgo/go/crypto/openpgp/armor/armor_test.go
deleted file mode 100644
index 9334e94e96c..00000000000
--- a/libgo/go/crypto/openpgp/armor/armor_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package armor
-
-import (
- "bytes"
- "hash/adler32"
- "io/ioutil"
- "testing"
-)
-
-func TestDecodeEncode(t *testing.T) {
- buf := bytes.NewBuffer([]byte(armorExample1))
- result, err := Decode(buf)
- if err != nil {
- t.Error(err)
- }
- expectedType := "PGP SIGNATURE"
- if result.Type != expectedType {
- t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
- }
- if len(result.Header) != 1 {
- t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
- }
- v, ok := result.Header["Version"]
- if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
- t.Errorf("result.Header: got:%#v", result.Header)
- }
-
- contents, err := ioutil.ReadAll(result.Body)
- if err != nil {
- t.Error(err)
- }
-
- if adler32.Checksum(contents) != 0x27b144be {
- t.Errorf("contents: got: %x", contents)
- }
-
- buf = bytes.NewBuffer(nil)
- w, err := Encode(buf, result.Type, result.Header)
- if err != nil {
- t.Error(err)
- }
- _, err = w.Write(contents)
- if err != nil {
- t.Error(err)
- }
- w.Close()
-
- if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
- t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
- }
-}
-
-func TestLongHeader(t *testing.T) {
- buf := bytes.NewBuffer([]byte(armorLongLine))
- result, err := Decode(buf)
- if err != nil {
- t.Error(err)
- return
- }
- value, ok := result.Header["Version"]
- if !ok {
- t.Errorf("missing Version header")
- }
- if value != longValueExpected {
- t.Errorf("got: %s want: %s", value, longValueExpected)
- }
-}
-
-const armorExample1 = `-----BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.10 (GNU/Linux)
-
-iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
-4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
-p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
-TxRjs+fJCIFuo71xb1g=
-=/teI
------END PGP SIGNATURE-----`
-
-const armorLongLine = `-----BEGIN PGP SIGNATURE-----
-Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
-
-iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
-kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
-cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
-byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
-WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
-okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
-=wfQG
------END PGP SIGNATURE-----`
-
-const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/libgo/go/crypto/openpgp/armor/encode.go b/libgo/go/crypto/openpgp/armor/encode.go
deleted file mode 100644
index 6f07582c37c..00000000000
--- a/libgo/go/crypto/openpgp/armor/encode.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package armor
-
-import (
- "encoding/base64"
- "io"
-)
-
-var armorHeaderSep = []byte(": ")
-var blockEnd = []byte("\n=")
-var newline = []byte("\n")
-var armorEndOfLineOut = []byte("-----\n")
-
-// writeSlices writes its arguments to the given Writer.
-func writeSlices(out io.Writer, slices ...[]byte) (err error) {
- for _, s := range slices {
- _, err = out.Write(s)
- if err != nil {
- return err
- }
- }
- return
-}
-
-// lineBreaker breaks data across several lines, all of the same byte length
-// (except possibly the last). Lines are broken with a single '\n'.
-type lineBreaker struct {
- lineLength int
- line []byte
- used int
- out io.Writer
- haveWritten bool
-}
-
-func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
- return &lineBreaker{
- lineLength: lineLength,
- line: make([]byte, lineLength),
- used: 0,
- out: out,
- }
-}
-
-func (l *lineBreaker) Write(b []byte) (n int, err error) {
- n = len(b)
-
- if n == 0 {
- return
- }
-
- if l.used == 0 && l.haveWritten {
- _, err = l.out.Write([]byte{'\n'})
- if err != nil {
- return
- }
- }
-
- if l.used+len(b) < l.lineLength {
- l.used += copy(l.line[l.used:], b)
- return
- }
-
- l.haveWritten = true
- _, err = l.out.Write(l.line[0:l.used])
- if err != nil {
- return
- }
- excess := l.lineLength - l.used
- l.used = 0
-
- _, err = l.out.Write(b[0:excess])
- if err != nil {
- return
- }
-
- _, err = l.Write(b[excess:])
- return
-}
-
-func (l *lineBreaker) Close() (err error) {
- if l.used > 0 {
- _, err = l.out.Write(l.line[0:l.used])
- if err != nil {
- return
- }
- }
-
- return
-}
-
-// encoding keeps track of a running CRC24 over the data which has been written
-// to it and outputs a OpenPGP checksum when closed, followed by an armor
-// trailer.
-//
-// It's built into a stack of io.Writers:
-// encoding -> base64 encoder -> lineBreaker -> out
-type encoding struct {
- out io.Writer
- breaker *lineBreaker
- b64 io.WriteCloser
- crc uint32
- blockType []byte
-}
-
-func (e *encoding) Write(data []byte) (n int, err error) {
- e.crc = crc24(e.crc, data)
- return e.b64.Write(data)
-}
-
-func (e *encoding) Close() (err error) {
- err = e.b64.Close()
- if err != nil {
- return
- }
- e.breaker.Close()
-
- var checksumBytes [3]byte
- checksumBytes[0] = byte(e.crc >> 16)
- checksumBytes[1] = byte(e.crc >> 8)
- checksumBytes[2] = byte(e.crc)
-
- var b64ChecksumBytes [4]byte
- base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
-
- return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
-}
-
-// Encode returns a WriteCloser which will encode the data written to it in
-// OpenPGP armor.
-func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
- bType := []byte(blockType)
- err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
- if err != nil {
- return
- }
-
- for k, v := range headers {
- err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
- if err != nil {
- return
- }
- }
-
- _, err = out.Write(newline)
- if err != nil {
- return
- }
-
- e := &encoding{
- out: out,
- breaker: newLineBreaker(out, 64),
- crc: crc24Init,
- blockType: bType,
- }
- e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
- return e, nil
-}
diff --git a/libgo/go/crypto/openpgp/canonical_text.go b/libgo/go/crypto/openpgp/canonical_text.go
deleted file mode 100644
index e601e389f12..00000000000
--- a/libgo/go/crypto/openpgp/canonical_text.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import "hash"
-
-// NewCanonicalTextHash reformats text written to it into the canonical
-// form and then applies the hash h. See RFC 4880, section 5.2.1.
-func NewCanonicalTextHash(h hash.Hash) hash.Hash {
- return &canonicalTextHash{h, 0}
-}
-
-type canonicalTextHash struct {
- h hash.Hash
- s int
-}
-
-var newline = []byte{'\r', '\n'}
-
-func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
- start := 0
-
- for i, c := range buf {
- switch cth.s {
- case 0:
- if c == '\r' {
- cth.s = 1
- } else if c == '\n' {
- cth.h.Write(buf[start:i])
- cth.h.Write(newline)
- start = i + 1
- }
- case 1:
- cth.s = 0
- }
- }
-
- cth.h.Write(buf[start:])
- return len(buf), nil
-}
-
-func (cth *canonicalTextHash) Sum(in []byte) []byte {
- return cth.h.Sum(in)
-}
-
-func (cth *canonicalTextHash) Reset() {
- cth.h.Reset()
- cth.s = 0
-}
-
-func (cth *canonicalTextHash) Size() int {
- return cth.h.Size()
-}
-
-func (cth *canonicalTextHash) BlockSize() int {
- return cth.h.BlockSize()
-}
diff --git a/libgo/go/crypto/openpgp/canonical_text_test.go b/libgo/go/crypto/openpgp/canonical_text_test.go
deleted file mode 100644
index 8f3ba2a8814..00000000000
--- a/libgo/go/crypto/openpgp/canonical_text_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import (
- "bytes"
- "testing"
-)
-
-type recordingHash struct {
- buf *bytes.Buffer
-}
-
-func (r recordingHash) Write(b []byte) (n int, err error) {
- return r.buf.Write(b)
-}
-
-func (r recordingHash) Sum(in []byte) []byte {
- return append(in, r.buf.Bytes()...)
-}
-
-func (r recordingHash) Reset() {
- panic("shouldn't be called")
-}
-
-func (r recordingHash) Size() int {
- panic("shouldn't be called")
-}
-
-func (r recordingHash) BlockSize() int {
- panic("shouldn't be called")
-}
-
-func testCanonicalText(t *testing.T, input, expected string) {
- r := recordingHash{bytes.NewBuffer(nil)}
- c := NewCanonicalTextHash(r)
- c.Write([]byte(input))
- result := c.Sum(nil)
- if expected != string(result) {
- t.Errorf("input: %x got: %x want: %x", input, result, expected)
- }
-}
-
-func TestCanonicalText(t *testing.T) {
- testCanonicalText(t, "foo\n", "foo\r\n")
- testCanonicalText(t, "foo", "foo")
- testCanonicalText(t, "foo\r\n", "foo\r\n")
- testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
- testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
-}
diff --git a/libgo/go/crypto/openpgp/elgamal/elgamal.go b/libgo/go/crypto/openpgp/elgamal/elgamal.go
deleted file mode 100644
index a553bdee8dd..00000000000
--- a/libgo/go/crypto/openpgp/elgamal/elgamal.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package elgamal implements ElGamal encryption, suitable for OpenPGP,
-// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
-// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
-// n. 4, 1985, pp. 469-472.
-//
-// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
-// unsuitable for other protocols. RSA should be used in preference in any
-// case.
-package elgamal
-
-import (
- "crypto/rand"
- "crypto/subtle"
- "errors"
- "io"
- "math/big"
-)
-
-// PublicKey represents an ElGamal public key.
-type PublicKey struct {
- G, P, Y *big.Int
-}
-
-// PrivateKey represents an ElGamal private key.
-type PrivateKey struct {
- PublicKey
- X *big.Int
-}
-
-// Encrypt encrypts the given message to the given public key. The result is a
-// pair of integers. Errors can result from reading random, or because msg is
-// too large to be encrypted to the public key.
-func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
- pLen := (pub.P.BitLen() + 7) / 8
- if len(msg) > pLen-11 {
- err = errors.New("elgamal: message too long")
- return
- }
-
- // EM = 0x02 || PS || 0x00 || M
- em := make([]byte, pLen-1)
- em[0] = 2
- ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
- err = nonZeroRandomBytes(ps, random)
- if err != nil {
- return
- }
- em[len(em)-len(msg)-1] = 0
- copy(mm, msg)
-
- m := new(big.Int).SetBytes(em)
-
- k, err := rand.Int(random, pub.P)
- if err != nil {
- return
- }
-
- c1 = new(big.Int).Exp(pub.G, k, pub.P)
- s := new(big.Int).Exp(pub.Y, k, pub.P)
- c2 = s.Mul(s, m)
- c2.Mod(c2, pub.P)
-
- return
-}
-
-// Decrypt takes two integers, resulting from an ElGamal encryption, and
-// returns the plaintext of the message. An error can result only if the
-// ciphertext is invalid. Users should keep in mind that this is a padding
-// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
-// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks
-// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
-// Bleichenbacher, Advances in Cryptology (Crypto '98),
-func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
- s := new(big.Int).Exp(c1, priv.X, priv.P)
- s.ModInverse(s, priv.P)
- s.Mul(s, c2)
- s.Mod(s, priv.P)
- em := s.Bytes()
-
- firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
-
- // The remainder of the plaintext must be a string of non-zero random
- // octets, followed by a 0, followed by the message.
- // lookingForIndex: 1 iff we are still looking for the zero.
- // index: the offset of the first zero byte.
- var lookingForIndex, index int
- lookingForIndex = 1
-
- for i := 1; i < len(em); i++ {
- equals0 := subtle.ConstantTimeByteEq(em[i], 0)
- index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
- lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
- }
-
- if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
- return nil, errors.New("elgamal: decryption error")
- }
- return em[index+1:], nil
-}
-
-// nonZeroRandomBytes fills the given slice with non-zero random octets.
-func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
- _, err = io.ReadFull(rand, s)
- if err != nil {
- return
- }
-
- for i := 0; i < len(s); i++ {
- for s[i] == 0 {
- _, err = io.ReadFull(rand, s[i:i+1])
- if err != nil {
- return
- }
- }
- }
-
- return
-}
diff --git a/libgo/go/crypto/openpgp/elgamal/elgamal_test.go b/libgo/go/crypto/openpgp/elgamal/elgamal_test.go
deleted file mode 100644
index c4f99f5c48c..00000000000
--- a/libgo/go/crypto/openpgp/elgamal/elgamal_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package elgamal
-
-import (
- "bytes"
- "crypto/rand"
- "math/big"
- "testing"
-)
-
-// This is the 1024-bit MODP group from RFC 5114, section 2.1:
-const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
-
-const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
-
-func fromHex(hex string) *big.Int {
- n, ok := new(big.Int).SetString(hex, 16)
- if !ok {
- panic("failed to parse hex number")
- }
- return n
-}
-
-func TestEncryptDecrypt(t *testing.T) {
- priv := &PrivateKey{
- PublicKey: PublicKey{
- G: fromHex(generatorHex),
- P: fromHex(primeHex),
- },
- X: fromHex("42"),
- }
- priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
-
- message := []byte("hello world")
- c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
- if err != nil {
- t.Errorf("error encrypting: %s", err)
- }
- message2, err := Decrypt(priv, c1, c2)
- if err != nil {
- t.Errorf("error decrypting: %s", err)
- }
- if !bytes.Equal(message2, message) {
- t.Errorf("decryption failed, got: %x, want: %x", message2, message)
- }
-}
diff --git a/libgo/go/crypto/openpgp/errors/errors.go b/libgo/go/crypto/openpgp/errors/errors.go
deleted file mode 100644
index c434b764c9b..00000000000
--- a/libgo/go/crypto/openpgp/errors/errors.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package errors contains common error types for the OpenPGP packages.
-package errors
-
-import (
- "strconv"
-)
-
-// A StructuralError is returned when OpenPGP data is found to be syntactically
-// invalid.
-type StructuralError string
-
-func (s StructuralError) Error() string {
- return "OpenPGP data invalid: " + string(s)
-}
-
-// UnsupportedError indicates that, although the OpenPGP data is valid, it
-// makes use of currently unimplemented features.
-type UnsupportedError string
-
-func (s UnsupportedError) Error() string {
- return "OpenPGP feature unsupported: " + string(s)
-}
-
-// InvalidArgumentError indicates that the caller is in error and passed an
-// incorrect value.
-type InvalidArgumentError string
-
-func (i InvalidArgumentError) Error() string {
- return "OpenPGP argument invalid: " + string(i)
-}
-
-// SignatureError indicates that a syntactically valid signature failed to
-// validate.
-type SignatureError string
-
-func (b SignatureError) Error() string {
- return "OpenPGP signature invalid: " + string(b)
-}
-
-type keyIncorrectError int
-
-func (ki keyIncorrectError) Error() string {
- return "the given key was incorrect"
-}
-
-var KeyIncorrectError = keyIncorrectError(0)
-
-type unknownIssuerError int
-
-func (unknownIssuerError) Error() string {
- return "signature make by unknown entity"
-}
-
-var UnknownIssuerError = unknownIssuerError(0)
-
-type UnknownPacketTypeError uint8
-
-func (upte UnknownPacketTypeError) Error() string {
- return "unknown OpenPGP packet type: " + strconv.Itoa(int(upte))
-}
diff --git a/libgo/go/crypto/openpgp/keys.go b/libgo/go/crypto/openpgp/keys.go
deleted file mode 100644
index 624a5ea8a76..00000000000
--- a/libgo/go/crypto/openpgp/keys.go
+++ /dev/null
@@ -1,546 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import (
- "crypto"
- "crypto/openpgp/armor"
- "crypto/openpgp/errors"
- "crypto/openpgp/packet"
- "crypto/rand"
- "crypto/rsa"
- "io"
- "time"
-)
-
-// PublicKeyType is the armor type for a PGP public key.
-var PublicKeyType = "PGP PUBLIC KEY BLOCK"
-
-// PrivateKeyType is the armor type for a PGP private key.
-var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
-
-// An Entity represents the components of an OpenPGP key: a primary public key
-// (which must be a signing key), one or more identities claimed by that key,
-// and zero or more subkeys, which may be encryption keys.
-type Entity struct {
- PrimaryKey *packet.PublicKey
- PrivateKey *packet.PrivateKey
- Identities map[string]*Identity // indexed by Identity.Name
- Subkeys []Subkey
-}
-
-// An Identity represents an identity claimed by an Entity and zero or more
-// assertions by other entities about that claim.
-type Identity struct {
- Name string // by convention, has the form "Full Name (comment) <email@example.com>"
- UserId *packet.UserId
- SelfSignature *packet.Signature
- Signatures []*packet.Signature
-}
-
-// A Subkey is an additional public key in an Entity. Subkeys can be used for
-// encryption.
-type Subkey struct {
- PublicKey *packet.PublicKey
- PrivateKey *packet.PrivateKey
- Sig *packet.Signature
-}
-
-// A Key identifies a specific public key in an Entity. This is either the
-// Entity's primary key or a subkey.
-type Key struct {
- Entity *Entity
- PublicKey *packet.PublicKey
- PrivateKey *packet.PrivateKey
- SelfSignature *packet.Signature
-}
-
-// A KeyRing provides access to public and private keys.
-type KeyRing interface {
- // KeysById returns the set of keys that have the given key id.
- KeysById(id uint64) []Key
- // DecryptionKeys returns all private keys that are valid for
- // decryption.
- DecryptionKeys() []Key
-}
-
-// primaryIdentity returns the Identity marked as primary or the first identity
-// if none are so marked.
-func (e *Entity) primaryIdentity() *Identity {
- var firstIdentity *Identity
- for _, ident := range e.Identities {
- if firstIdentity == nil {
- firstIdentity = ident
- }
- if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
- return ident
- }
- }
- return firstIdentity
-}
-
-// encryptionKey returns the best candidate Key for encrypting a message to the
-// given Entity.
-func (e *Entity) encryptionKey() Key {
- candidateSubkey := -1
-
- for i, subkey := range e.Subkeys {
- if subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications && subkey.PublicKey.PubKeyAlgo.CanEncrypt() {
- candidateSubkey = i
- break
- }
- }
-
- i := e.primaryIdentity()
-
- if e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
- // If we don't have any candidate subkeys for encryption and
- // the primary key doesn't have any usage metadata then we
- // assume that the primary key is ok. Or, if the primary key is
- // marked as ok to encrypt to, then we can obviously use it.
- if candidateSubkey == -1 && !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && i.SelfSignature.FlagsValid {
- return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}
- }
- }
-
- if candidateSubkey != -1 {
- subkey := e.Subkeys[candidateSubkey]
- return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}
- }
-
- // This Entity appears to be signing only.
- return Key{}
-}
-
-// signingKey return the best candidate Key for signing a message with this
-// Entity.
-func (e *Entity) signingKey() Key {
- candidateSubkey := -1
-
- for i, subkey := range e.Subkeys {
- if subkey.Sig.FlagsValid && subkey.Sig.FlagSign && subkey.PublicKey.PubKeyAlgo.CanSign() {
- candidateSubkey = i
- break
- }
- }
-
- i := e.primaryIdentity()
-
- // If we have no candidate subkey then we assume that it's ok to sign
- // with the primary key.
- if candidateSubkey == -1 || i.SelfSignature.FlagsValid && i.SelfSignature.FlagSign {
- return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}
- }
-
- subkey := e.Subkeys[candidateSubkey]
- return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}
-}
-
-// An EntityList contains one or more Entities.
-type EntityList []*Entity
-
-// KeysById returns the set of keys that have the given key id.
-func (el EntityList) KeysById(id uint64) (keys []Key) {
- for _, e := range el {
- if e.PrimaryKey.KeyId == id {
- var selfSig *packet.Signature
- for _, ident := range e.Identities {
- if selfSig == nil {
- selfSig = ident.SelfSignature
- } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
- selfSig = ident.SelfSignature
- break
- }
- }
- keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
- }
-
- for _, subKey := range e.Subkeys {
- if subKey.PublicKey.KeyId == id {
- keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
- }
- }
- }
- return
-}
-
-// DecryptionKeys returns all private keys that are valid for decryption.
-func (el EntityList) DecryptionKeys() (keys []Key) {
- for _, e := range el {
- for _, subKey := range e.Subkeys {
- if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
- keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
- }
- }
- }
- return
-}
-
-// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
-func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
- block, err := armor.Decode(r)
- if err == io.EOF {
- return nil, errors.InvalidArgumentError("no armored data found")
- }
- if err != nil {
- return nil, err
- }
- if block.Type != PublicKeyType && block.Type != PrivateKeyType {
- return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
- }
-
- return ReadKeyRing(block.Body)
-}
-
-// ReadKeyRing reads one or more public/private keys. Unsupported keys are
-// ignored as long as at least a single valid key is found.
-func ReadKeyRing(r io.Reader) (el EntityList, err error) {
- packets := packet.NewReader(r)
- var lastUnsupportedError error
-
- for {
- var e *Entity
- e, err = readEntity(packets)
- if err != nil {
- if _, ok := err.(errors.UnsupportedError); ok {
- lastUnsupportedError = err
- err = readToNextPublicKey(packets)
- }
- if err == io.EOF {
- err = nil
- break
- }
- if err != nil {
- el = nil
- break
- }
- } else {
- el = append(el, e)
- }
- }
-
- if len(el) == 0 && err == nil {
- err = lastUnsupportedError
- }
- return
-}
-
-// readToNextPublicKey reads packets until the start of the entity and leaves
-// the first packet of the new entity in the Reader.
-func readToNextPublicKey(packets *packet.Reader) (err error) {
- var p packet.Packet
- for {
- p, err = packets.Next()
- if err == io.EOF {
- return
- } else if err != nil {
- if _, ok := err.(errors.UnsupportedError); ok {
- err = nil
- continue
- }
- return
- }
-
- if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
- packets.Unread(p)
- return
- }
- }
-
- panic("unreachable")
-}
-
-// readEntity reads an entity (public key, identities, subkeys etc) from the
-// given Reader.
-func readEntity(packets *packet.Reader) (*Entity, error) {
- e := new(Entity)
- e.Identities = make(map[string]*Identity)
-
- p, err := packets.Next()
- if err != nil {
- return nil, err
- }
-
- var ok bool
- if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
- if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
- packets.Unread(p)
- return nil, errors.StructuralError("first packet was not a public/private key")
- } else {
- e.PrimaryKey = &e.PrivateKey.PublicKey
- }
- }
-
- if !e.PrimaryKey.PubKeyAlgo.CanSign() {
- return nil, errors.StructuralError("primary key cannot be used for signatures")
- }
-
- var current *Identity
-EachPacket:
- for {
- p, err := packets.Next()
- if err == io.EOF {
- break
- } else if err != nil {
- return nil, err
- }
-
- switch pkt := p.(type) {
- case *packet.UserId:
- current = new(Identity)
- current.Name = pkt.Id
- current.UserId = pkt
- e.Identities[pkt.Id] = current
-
- for {
- p, err = packets.Next()
- if err == io.EOF {
- return nil, io.ErrUnexpectedEOF
- } else if err != nil {
- return nil, err
- }
-
- sig, ok := p.(*packet.Signature)
- if !ok {
- return nil, errors.StructuralError("user ID packet not followed by self-signature")
- }
-
- if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
- if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
- return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
- }
- current.SelfSignature = sig
- break
- }
- current.Signatures = append(current.Signatures, sig)
- }
- case *packet.Signature:
- if current == nil {
- return nil, errors.StructuralError("signature packet found before user id packet")
- }
- current.Signatures = append(current.Signatures, pkt)
- case *packet.PrivateKey:
- if pkt.IsSubkey == false {
- packets.Unread(p)
- break EachPacket
- }
- err = addSubkey(e, packets, &pkt.PublicKey, pkt)
- if err != nil {
- return nil, err
- }
- case *packet.PublicKey:
- if pkt.IsSubkey == false {
- packets.Unread(p)
- break EachPacket
- }
- err = addSubkey(e, packets, pkt, nil)
- if err != nil {
- return nil, err
- }
- default:
- // we ignore unknown packets
- }
- }
-
- if len(e.Identities) == 0 {
- return nil, errors.StructuralError("entity without any identities")
- }
-
- return e, nil
-}
-
-func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
- var subKey Subkey
- subKey.PublicKey = pub
- subKey.PrivateKey = priv
- p, err := packets.Next()
- if err == io.EOF {
- return io.ErrUnexpectedEOF
- }
- if err != nil {
- return errors.StructuralError("subkey signature invalid: " + err.Error())
- }
- var ok bool
- subKey.Sig, ok = p.(*packet.Signature)
- if !ok {
- return errors.StructuralError("subkey packet not followed by signature")
- }
- if subKey.Sig.SigType != packet.SigTypeSubkeyBinding {
- return errors.StructuralError("subkey signature with wrong type")
- }
- err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
- if err != nil {
- return errors.StructuralError("subkey signature invalid: " + err.Error())
- }
- e.Subkeys = append(e.Subkeys, subKey)
- return nil
-}
-
-const defaultRSAKeyBits = 2048
-
-// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
-// single identity composed of the given full name, comment and email, any of
-// which may be empty but must not contain any of "()<>\x00".
-func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email string) (*Entity, error) {
- uid := packet.NewUserId(name, comment, email)
- if uid == nil {
- return nil, errors.InvalidArgumentError("user id field contained invalid characters")
- }
- signingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
- if err != nil {
- return nil, err
- }
- encryptingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
- if err != nil {
- return nil, err
- }
-
- e := &Entity{
- PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
- PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
- Identities: make(map[string]*Identity),
- }
- isPrimaryId := true
- e.Identities[uid.Id] = &Identity{
- Name: uid.Name,
- UserId: uid,
- SelfSignature: &packet.Signature{
- CreationTime: currentTime,
- SigType: packet.SigTypePositiveCert,
- PubKeyAlgo: packet.PubKeyAlgoRSA,
- Hash: crypto.SHA256,
- IsPrimaryId: &isPrimaryId,
- FlagsValid: true,
- FlagSign: true,
- FlagCertify: true,
- IssuerKeyId: &e.PrimaryKey.KeyId,
- },
- }
-
- e.Subkeys = make([]Subkey, 1)
- e.Subkeys[0] = Subkey{
- PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
- PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
- Sig: &packet.Signature{
- CreationTime: currentTime,
- SigType: packet.SigTypeSubkeyBinding,
- PubKeyAlgo: packet.PubKeyAlgoRSA,
- Hash: crypto.SHA256,
- FlagsValid: true,
- FlagEncryptStorage: true,
- FlagEncryptCommunications: true,
- IssuerKeyId: &e.PrimaryKey.KeyId,
- },
- }
- e.Subkeys[0].PublicKey.IsSubkey = true
- e.Subkeys[0].PrivateKey.IsSubkey = true
-
- return e, nil
-}
-
-// SerializePrivate serializes an Entity, including private key material, to
-// the given Writer. For now, it must only be used on an Entity returned from
-// NewEntity.
-func (e *Entity) SerializePrivate(w io.Writer) (err error) {
- err = e.PrivateKey.Serialize(w)
- if err != nil {
- return
- }
- for _, ident := range e.Identities {
- err = ident.UserId.Serialize(w)
- if err != nil {
- return
- }
- err = ident.SelfSignature.SignUserId(rand.Reader, ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
- if err != nil {
- return
- }
- err = ident.SelfSignature.Serialize(w)
- if err != nil {
- return
- }
- }
- for _, subkey := range e.Subkeys {
- err = subkey.PrivateKey.Serialize(w)
- if err != nil {
- return
- }
- err = subkey.Sig.SignKey(rand.Reader, subkey.PublicKey, e.PrivateKey)
- if err != nil {
- return
- }
- err = subkey.Sig.Serialize(w)
- if err != nil {
- return
- }
- }
- return nil
-}
-
-// Serialize writes the public part of the given Entity to w. (No private
-// key material will be output).
-func (e *Entity) Serialize(w io.Writer) error {
- err := e.PrimaryKey.Serialize(w)
- if err != nil {
- return err
- }
- for _, ident := range e.Identities {
- err = ident.UserId.Serialize(w)
- if err != nil {
- return err
- }
- err = ident.SelfSignature.Serialize(w)
- if err != nil {
- return err
- }
- for _, sig := range ident.Signatures {
- err = sig.Serialize(w)
- if err != nil {
- return err
- }
- }
- }
- for _, subkey := range e.Subkeys {
- err = subkey.PublicKey.Serialize(w)
- if err != nil {
- return err
- }
- err = subkey.Sig.Serialize(w)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// SignIdentity adds a signature to e, from signer, attesting that identity is
-// associated with e. The provided identity must already be an element of
-// e.Identities and the private key of signer must have been decrypted if
-// necessary.
-func (e *Entity) SignIdentity(identity string, signer *Entity) error {
- if signer.PrivateKey == nil {
- return errors.InvalidArgumentError("signing Entity must have a private key")
- }
- if signer.PrivateKey.Encrypted {
- return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
- }
- ident, ok := e.Identities[identity]
- if !ok {
- return errors.InvalidArgumentError("given identity string not found in Entity")
- }
-
- sig := &packet.Signature{
- SigType: packet.SigTypeGenericCert,
- PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
- Hash: crypto.SHA256,
- CreationTime: time.Now(),
- IssuerKeyId: &signer.PrivateKey.KeyId,
- }
- if err := sig.SignKey(rand.Reader, e.PrimaryKey, signer.PrivateKey); err != nil {
- return err
- }
- ident.Signatures = append(ident.Signatures, sig)
- return nil
-}
diff --git a/libgo/go/crypto/openpgp/packet/compressed.go b/libgo/go/crypto/openpgp/packet/compressed.go
deleted file mode 100644
index 36736e34a0e..00000000000
--- a/libgo/go/crypto/openpgp/packet/compressed.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "compress/flate"
- "compress/zlib"
- "crypto/openpgp/errors"
- "io"
- "strconv"
-)
-
-// Compressed represents a compressed OpenPGP packet. The decompressed contents
-// will contain more OpenPGP packets. See RFC 4880, section 5.6.
-type Compressed struct {
- Body io.Reader
-}
-
-func (c *Compressed) parse(r io.Reader) error {
- var buf [1]byte
- _, err := readFull(r, buf[:])
- if err != nil {
- return err
- }
-
- switch buf[0] {
- case 1:
- c.Body = flate.NewReader(r)
- case 2:
- c.Body, err = zlib.NewReader(r)
- default:
- err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
- }
-
- return err
-}
diff --git a/libgo/go/crypto/openpgp/packet/compressed_test.go b/libgo/go/crypto/openpgp/packet/compressed_test.go
deleted file mode 100644
index cb2d70bd411..00000000000
--- a/libgo/go/crypto/openpgp/packet/compressed_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "encoding/hex"
- "io"
- "io/ioutil"
- "testing"
-)
-
-func TestCompressed(t *testing.T) {
- packet, err := Read(readerFromHex(compressedHex))
- if err != nil {
- t.Errorf("failed to read Compressed: %s", err)
- return
- }
-
- c, ok := packet.(*Compressed)
- if !ok {
- t.Error("didn't find Compressed packet")
- return
- }
-
- contents, err := ioutil.ReadAll(c.Body)
- if err != nil && err != io.EOF {
- t.Error(err)
- return
- }
-
- expected, _ := hex.DecodeString(compressedExpectedHex)
- if !bytes.Equal(expected, contents) {
- t.Errorf("got:%x want:%x", contents, expected)
- }
-}
-
-const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
-const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"
diff --git a/libgo/go/crypto/openpgp/packet/encrypted_key.go b/libgo/go/crypto/openpgp/packet/encrypted_key.go
deleted file mode 100644
index 479a643935e..00000000000
--- a/libgo/go/crypto/openpgp/packet/encrypted_key.go
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "crypto/openpgp/elgamal"
- "crypto/openpgp/errors"
- "crypto/rand"
- "crypto/rsa"
- "encoding/binary"
- "io"
- "math/big"
- "strconv"
-)
-
-const encryptedKeyVersion = 3
-
-// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
-// section 5.1.
-type EncryptedKey struct {
- KeyId uint64
- Algo PublicKeyAlgorithm
- CipherFunc CipherFunction // only valid after a successful Decrypt
- Key []byte // only valid after a successful Decrypt
-
- encryptedMPI1, encryptedMPI2 []byte
-}
-
-func (e *EncryptedKey) parse(r io.Reader) (err error) {
- var buf [10]byte
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
- if buf[0] != encryptedKeyVersion {
- return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
- }
- e.KeyId = binary.BigEndian.Uint64(buf[1:9])
- e.Algo = PublicKeyAlgorithm(buf[9])
- switch e.Algo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
- e.encryptedMPI1, _, err = readMPI(r)
- case PubKeyAlgoElGamal:
- e.encryptedMPI1, _, err = readMPI(r)
- if err != nil {
- return
- }
- e.encryptedMPI2, _, err = readMPI(r)
- }
- _, err = consumeAll(r)
- return
-}
-
-func checksumKeyMaterial(key []byte) uint16 {
- var checksum uint16
- for _, v := range key {
- checksum += uint16(v)
- }
- return checksum
-}
-
-// Decrypt decrypts an encrypted session key with the given private key. The
-// private key must have been decrypted first.
-func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
- var err error
- var b []byte
-
- // TODO(agl): use session key decryption routines here to avoid
- // padding oracle attacks.
- switch priv.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
- b, err = rsa.DecryptPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
- case PubKeyAlgoElGamal:
- c1 := new(big.Int).SetBytes(e.encryptedMPI1)
- c2 := new(big.Int).SetBytes(e.encryptedMPI2)
- b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
- default:
- err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
- }
-
- if err != nil {
- return err
- }
-
- e.CipherFunc = CipherFunction(b[0])
- e.Key = b[1 : len(b)-2]
- expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
- checksum := checksumKeyMaterial(e.Key)
- if checksum != expectedChecksum {
- return errors.StructuralError("EncryptedKey checksum incorrect")
- }
-
- return nil
-}
-
-// SerializeEncryptedKey serializes an encrypted key packet to w that contains
-// key, encrypted to pub.
-func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFunc CipherFunction, key []byte) error {
- var buf [10]byte
- buf[0] = encryptedKeyVersion
- binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
- buf[9] = byte(pub.PubKeyAlgo)
-
- keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */ )
- keyBlock[0] = byte(cipherFunc)
- copy(keyBlock[1:], key)
- checksum := checksumKeyMaterial(key)
- keyBlock[1+len(key)] = byte(checksum >> 8)
- keyBlock[1+len(key)+1] = byte(checksum)
-
- switch pub.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
- return serializeEncryptedKeyRSA(w, rand, buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
- case PubKeyAlgoElGamal:
- return serializeEncryptedKeyElGamal(w, rand, buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
- case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
- return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
- }
-
- return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
-}
-
-func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
- cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
- if err != nil {
- return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
- }
-
- packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
-
- err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
- if err != nil {
- return err
- }
- _, err = w.Write(header[:])
- if err != nil {
- return err
- }
- return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
-}
-
-func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
- c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
- if err != nil {
- return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
- }
-
- packetLen := 10 /* header length */
- packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
- packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
-
- err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
- if err != nil {
- return err
- }
- _, err = w.Write(header[:])
- if err != nil {
- return err
- }
- err = writeBig(w, c1)
- if err != nil {
- return err
- }
- return writeBig(w, c2)
-}
diff --git a/libgo/go/crypto/openpgp/packet/encrypted_key_test.go b/libgo/go/crypto/openpgp/packet/encrypted_key_test.go
deleted file mode 100644
index 2b8eff7b3a9..00000000000
--- a/libgo/go/crypto/openpgp/packet/encrypted_key_test.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto/rand"
- "crypto/rsa"
- "fmt"
- "math/big"
- "testing"
-)
-
-func bigFromBase10(s string) *big.Int {
- b, ok := new(big.Int).SetString(s, 10)
- if !ok {
- panic("bigFromBase10 failed")
- }
- return b
-}
-
-var encryptedKeyPub = rsa.PublicKey{
- E: 65537,
- N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
-}
-
-var encryptedKeyRSAPriv = &rsa.PrivateKey{
- PublicKey: encryptedKeyPub,
- D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
-}
-
-var encryptedKeyPriv = &PrivateKey{
- PublicKey: PublicKey{
- PubKeyAlgo: PubKeyAlgoRSA,
- },
- PrivateKey: encryptedKeyRSAPriv,
-}
-
-func TestDecryptingEncryptedKey(t *testing.T) {
- const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
- const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
-
- p, err := Read(readerFromHex(encryptedKeyHex))
- if err != nil {
- t.Errorf("error from Read: %s", err)
- return
- }
- ek, ok := p.(*EncryptedKey)
- if !ok {
- t.Errorf("didn't parse an EncryptedKey, got %#v", p)
- return
- }
-
- if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
- t.Errorf("unexpected EncryptedKey contents: %#v", ek)
- return
- }
-
- err = ek.Decrypt(encryptedKeyPriv)
- if err != nil {
- t.Errorf("error from Decrypt: %s", err)
- return
- }
-
- if ek.CipherFunc != CipherAES256 {
- t.Errorf("unexpected EncryptedKey contents: %#v", ek)
- return
- }
-
- keyHex := fmt.Sprintf("%x", ek.Key)
- if keyHex != expectedKeyHex {
- t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
- }
-}
-
-func TestEncryptingEncryptedKey(t *testing.T) {
- key := []byte{1, 2, 3, 4}
- const expectedKeyHex = "01020304"
- const keyId = 42
-
- pub := &PublicKey{
- PublicKey: &encryptedKeyPub,
- KeyId: keyId,
- PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
- }
-
- buf := new(bytes.Buffer)
- err := SerializeEncryptedKey(buf, rand.Reader, pub, CipherAES128, key)
- if err != nil {
- t.Errorf("error writing encrypted key packet: %s", err)
- }
-
- p, err := Read(buf)
- if err != nil {
- t.Errorf("error from Read: %s", err)
- return
- }
- ek, ok := p.(*EncryptedKey)
- if !ok {
- t.Errorf("didn't parse an EncryptedKey, got %#v", p)
- return
- }
-
- if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
- t.Errorf("unexpected EncryptedKey contents: %#v", ek)
- return
- }
-
- err = ek.Decrypt(encryptedKeyPriv)
- if err != nil {
- t.Errorf("error from Decrypt: %s", err)
- return
- }
-
- if ek.CipherFunc != CipherAES128 {
- t.Errorf("unexpected EncryptedKey contents: %#v", ek)
- return
- }
-
- keyHex := fmt.Sprintf("%x", ek.Key)
- if keyHex != expectedKeyHex {
- t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
- }
-}
diff --git a/libgo/go/crypto/openpgp/packet/literal.go b/libgo/go/crypto/openpgp/packet/literal.go
deleted file mode 100644
index 1a9ec6e51e8..00000000000
--- a/libgo/go/crypto/openpgp/packet/literal.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "encoding/binary"
- "io"
-)
-
-// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
-type LiteralData struct {
- IsBinary bool
- FileName string
- Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
- Body io.Reader
-}
-
-// ForEyesOnly returns whether the contents of the LiteralData have been marked
-// as especially sensitive.
-func (l *LiteralData) ForEyesOnly() bool {
- return l.FileName == "_CONSOLE"
-}
-
-func (l *LiteralData) parse(r io.Reader) (err error) {
- var buf [256]byte
-
- _, err = readFull(r, buf[:2])
- if err != nil {
- return
- }
-
- l.IsBinary = buf[0] == 'b'
- fileNameLen := int(buf[1])
-
- _, err = readFull(r, buf[:fileNameLen])
- if err != nil {
- return
- }
-
- l.FileName = string(buf[:fileNameLen])
-
- _, err = readFull(r, buf[:4])
- if err != nil {
- return
- }
-
- l.Time = binary.BigEndian.Uint32(buf[:4])
- l.Body = r
- return
-}
-
-// SerializeLiteral serializes a literal data packet to w and returns a
-// WriteCloser to which the data itself can be written and which MUST be closed
-// on completion. The fileName is truncated to 255 bytes.
-func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
- var buf [4]byte
- buf[0] = 't'
- if isBinary {
- buf[0] = 'b'
- }
- if len(fileName) > 255 {
- fileName = fileName[:255]
- }
- buf[1] = byte(len(fileName))
-
- inner, err := serializeStreamHeader(w, packetTypeLiteralData)
- if err != nil {
- return
- }
-
- _, err = inner.Write(buf[:2])
- if err != nil {
- return
- }
- _, err = inner.Write([]byte(fileName))
- if err != nil {
- return
- }
- binary.BigEndian.PutUint32(buf[:], time)
- _, err = inner.Write(buf[:])
- if err != nil {
- return
- }
-
- plaintext = inner
- return
-}
diff --git a/libgo/go/crypto/openpgp/packet/one_pass_signature.go b/libgo/go/crypto/openpgp/packet/one_pass_signature.go
deleted file mode 100644
index 822cfe9b8f6..00000000000
--- a/libgo/go/crypto/openpgp/packet/one_pass_signature.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "crypto"
- "crypto/openpgp/errors"
- "crypto/openpgp/s2k"
- "encoding/binary"
- "io"
- "strconv"
-)
-
-// OnePassSignature represents a one-pass signature packet. See RFC 4880,
-// section 5.4.
-type OnePassSignature struct {
- SigType SignatureType
- Hash crypto.Hash
- PubKeyAlgo PublicKeyAlgorithm
- KeyId uint64
- IsLast bool
-}
-
-const onePassSignatureVersion = 3
-
-func (ops *OnePassSignature) parse(r io.Reader) (err error) {
- var buf [13]byte
-
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
- if buf[0] != onePassSignatureVersion {
- err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
- }
-
- var ok bool
- ops.Hash, ok = s2k.HashIdToHash(buf[2])
- if !ok {
- return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
- }
-
- ops.SigType = SignatureType(buf[1])
- ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
- ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
- ops.IsLast = buf[12] != 0
- return
-}
-
-// Serialize marshals the given OnePassSignature to w.
-func (ops *OnePassSignature) Serialize(w io.Writer) error {
- var buf [13]byte
- buf[0] = onePassSignatureVersion
- buf[1] = uint8(ops.SigType)
- var ok bool
- buf[2], ok = s2k.HashToHashId(ops.Hash)
- if !ok {
- return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
- }
- buf[3] = uint8(ops.PubKeyAlgo)
- binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
- if ops.IsLast {
- buf[12] = 1
- }
-
- if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
- return err
- }
- _, err := w.Write(buf[:])
- return err
-}
diff --git a/libgo/go/crypto/openpgp/packet/packet.go b/libgo/go/crypto/openpgp/packet/packet.go
deleted file mode 100644
index f7c1964fd4c..00000000000
--- a/libgo/go/crypto/openpgp/packet/packet.go
+++ /dev/null
@@ -1,482 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package packet implements parsing and serialization of OpenPGP packets, as
-// specified in RFC 4880.
-package packet
-
-import (
- "crypto/aes"
- "crypto/cast5"
- "crypto/cipher"
- "crypto/openpgp/errors"
- "io"
- "math/big"
-)
-
-// readFull is the same as io.ReadFull except that reading zero bytes returns
-// ErrUnexpectedEOF rather than EOF.
-func readFull(r io.Reader, buf []byte) (n int, err error) {
- n, err = io.ReadFull(r, buf)
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return
-}
-
-// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
-func readLength(r io.Reader) (length int64, isPartial bool, err error) {
- var buf [4]byte
- _, err = readFull(r, buf[:1])
- if err != nil {
- return
- }
- switch {
- case buf[0] < 192:
- length = int64(buf[0])
- case buf[0] < 224:
- length = int64(buf[0]-192) << 8
- _, err = readFull(r, buf[0:1])
- if err != nil {
- return
- }
- length += int64(buf[0]) + 192
- case buf[0] < 255:
- length = int64(1) << (buf[0] & 0x1f)
- isPartial = true
- default:
- _, err = readFull(r, buf[0:4])
- if err != nil {
- return
- }
- length = int64(buf[0])<<24 |
- int64(buf[1])<<16 |
- int64(buf[2])<<8 |
- int64(buf[3])
- }
- return
-}
-
-// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
-// The continuation lengths are parsed and removed from the stream and EOF is
-// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
-type partialLengthReader struct {
- r io.Reader
- remaining int64
- isPartial bool
-}
-
-func (r *partialLengthReader) Read(p []byte) (n int, err error) {
- for r.remaining == 0 {
- if !r.isPartial {
- return 0, io.EOF
- }
- r.remaining, r.isPartial, err = readLength(r.r)
- if err != nil {
- return 0, err
- }
- }
-
- toRead := int64(len(p))
- if toRead > r.remaining {
- toRead = r.remaining
- }
-
- n, err = r.r.Read(p[:int(toRead)])
- r.remaining -= int64(n)
- if n < int(toRead) && err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return
-}
-
-// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
-// See RFC 4880, section 4.2.2.4.
-type partialLengthWriter struct {
- w io.WriteCloser
- lengthByte [1]byte
-}
-
-func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
- for len(p) > 0 {
- for power := uint(14); power < 32; power-- {
- l := 1 << power
- if len(p) >= l {
- w.lengthByte[0] = 224 + uint8(power)
- _, err = w.w.Write(w.lengthByte[:])
- if err != nil {
- return
- }
- var m int
- m, err = w.w.Write(p[:l])
- n += m
- if err != nil {
- return
- }
- p = p[l:]
- break
- }
- }
- }
- return
-}
-
-func (w *partialLengthWriter) Close() error {
- w.lengthByte[0] = 0
- _, err := w.w.Write(w.lengthByte[:])
- if err != nil {
- return err
- }
- return w.w.Close()
-}
-
-// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
-// underlying Reader returns EOF before the limit has been reached.
-type spanReader struct {
- r io.Reader
- n int64
-}
-
-func (l *spanReader) Read(p []byte) (n int, err error) {
- if l.n <= 0 {
- return 0, io.EOF
- }
- if int64(len(p)) > l.n {
- p = p[0:l.n]
- }
- n, err = l.r.Read(p)
- l.n -= int64(n)
- if l.n > 0 && err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return
-}
-
-// readHeader parses a packet header and returns an io.Reader which will return
-// the contents of the packet. See RFC 4880, section 4.2.
-func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
- var buf [4]byte
- _, err = io.ReadFull(r, buf[:1])
- if err != nil {
- return
- }
- if buf[0]&0x80 == 0 {
- err = errors.StructuralError("tag byte does not have MSB set")
- return
- }
- if buf[0]&0x40 == 0 {
- // Old format packet
- tag = packetType((buf[0] & 0x3f) >> 2)
- lengthType := buf[0] & 3
- if lengthType == 3 {
- length = -1
- contents = r
- return
- }
- lengthBytes := 1 << lengthType
- _, err = readFull(r, buf[0:lengthBytes])
- if err != nil {
- return
- }
- for i := 0; i < lengthBytes; i++ {
- length <<= 8
- length |= int64(buf[i])
- }
- contents = &spanReader{r, length}
- return
- }
-
- // New format packet
- tag = packetType(buf[0] & 0x3f)
- length, isPartial, err := readLength(r)
- if err != nil {
- return
- }
- if isPartial {
- contents = &partialLengthReader{
- remaining: length,
- isPartial: true,
- r: r,
- }
- length = -1
- } else {
- contents = &spanReader{r, length}
- }
- return
-}
-
-// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
-// 4.2.
-func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
- var buf [6]byte
- var n int
-
- buf[0] = 0x80 | 0x40 | byte(ptype)
- if length < 192 {
- buf[1] = byte(length)
- n = 2
- } else if length < 8384 {
- length -= 192
- buf[1] = 192 + byte(length>>8)
- buf[2] = byte(length)
- n = 3
- } else {
- buf[1] = 255
- buf[2] = byte(length >> 24)
- buf[3] = byte(length >> 16)
- buf[4] = byte(length >> 8)
- buf[5] = byte(length)
- n = 6
- }
-
- _, err = w.Write(buf[:n])
- return
-}
-
-// serializeStreamHeader writes an OpenPGP packet header to w where the
-// length of the packet is unknown. It returns a io.WriteCloser which can be
-// used to write the contents of the packet. See RFC 4880, section 4.2.
-func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
- var buf [1]byte
- buf[0] = 0x80 | 0x40 | byte(ptype)
- _, err = w.Write(buf[:])
- if err != nil {
- return
- }
- out = &partialLengthWriter{w: w}
- return
-}
-
-// Packet represents an OpenPGP packet. Users are expected to try casting
-// instances of this interface to specific packet types.
-type Packet interface {
- parse(io.Reader) error
-}
-
-// consumeAll reads from the given Reader until error, returning the number of
-// bytes read.
-func consumeAll(r io.Reader) (n int64, err error) {
- var m int
- var buf [1024]byte
-
- for {
- m, err = r.Read(buf[:])
- n += int64(m)
- if err == io.EOF {
- err = nil
- return
- }
- if err != nil {
- return
- }
- }
-
- panic("unreachable")
-}
-
-// packetType represents the numeric ids of the different OpenPGP packet types. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
-type packetType uint8
-
-const (
- packetTypeEncryptedKey packetType = 1
- packetTypeSignature packetType = 2
- packetTypeSymmetricKeyEncrypted packetType = 3
- packetTypeOnePassSignature packetType = 4
- packetTypePrivateKey packetType = 5
- packetTypePublicKey packetType = 6
- packetTypePrivateSubkey packetType = 7
- packetTypeCompressed packetType = 8
- packetTypeSymmetricallyEncrypted packetType = 9
- packetTypeLiteralData packetType = 11
- packetTypeUserId packetType = 13
- packetTypePublicSubkey packetType = 14
- packetTypeSymmetricallyEncryptedMDC packetType = 18
-)
-
-// Read reads a single OpenPGP packet from the given io.Reader. If there is an
-// error parsing a packet, the whole packet is consumed from the input.
-func Read(r io.Reader) (p Packet, err error) {
- tag, _, contents, err := readHeader(r)
- if err != nil {
- return
- }
-
- switch tag {
- case packetTypeEncryptedKey:
- p = new(EncryptedKey)
- case packetTypeSignature:
- p = new(Signature)
- case packetTypeSymmetricKeyEncrypted:
- p = new(SymmetricKeyEncrypted)
- case packetTypeOnePassSignature:
- p = new(OnePassSignature)
- case packetTypePrivateKey, packetTypePrivateSubkey:
- pk := new(PrivateKey)
- if tag == packetTypePrivateSubkey {
- pk.IsSubkey = true
- }
- p = pk
- case packetTypePublicKey, packetTypePublicSubkey:
- pk := new(PublicKey)
- if tag == packetTypePublicSubkey {
- pk.IsSubkey = true
- }
- p = pk
- case packetTypeCompressed:
- p = new(Compressed)
- case packetTypeSymmetricallyEncrypted:
- p = new(SymmetricallyEncrypted)
- case packetTypeLiteralData:
- p = new(LiteralData)
- case packetTypeUserId:
- p = new(UserId)
- case packetTypeSymmetricallyEncryptedMDC:
- se := new(SymmetricallyEncrypted)
- se.MDC = true
- p = se
- default:
- err = errors.UnknownPacketTypeError(tag)
- }
- if p != nil {
- err = p.parse(contents)
- }
- if err != nil {
- consumeAll(contents)
- }
- return
-}
-
-// SignatureType represents the different semantic meanings of an OpenPGP
-// signature. See RFC 4880, section 5.2.1.
-type SignatureType uint8
-
-const (
- SigTypeBinary SignatureType = 0
- SigTypeText = 1
- SigTypeGenericCert = 0x10
- SigTypePersonaCert = 0x11
- SigTypeCasualCert = 0x12
- SigTypePositiveCert = 0x13
- SigTypeSubkeyBinding = 0x18
-)
-
-// PublicKeyAlgorithm represents the different public key system specified for
-// OpenPGP. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
-type PublicKeyAlgorithm uint8
-
-const (
- PubKeyAlgoRSA PublicKeyAlgorithm = 1
- PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
- PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
- PubKeyAlgoElGamal PublicKeyAlgorithm = 16
- PubKeyAlgoDSA PublicKeyAlgorithm = 17
-)
-
-// CanEncrypt returns true if it's possible to encrypt a message to a public
-// key of the given type.
-func (pka PublicKeyAlgorithm) CanEncrypt() bool {
- switch pka {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
- return true
- }
- return false
-}
-
-// CanSign returns true if it's possible for a public key of the given type to
-// sign a message.
-func (pka PublicKeyAlgorithm) CanSign() bool {
- switch pka {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
- return true
- }
- return false
-}
-
-// CipherFunction represents the different block ciphers specified for OpenPGP. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
-type CipherFunction uint8
-
-const (
- CipherCAST5 CipherFunction = 3
- CipherAES128 CipherFunction = 7
- CipherAES192 CipherFunction = 8
- CipherAES256 CipherFunction = 9
-)
-
-// KeySize returns the key size, in bytes, of cipher.
-func (cipher CipherFunction) KeySize() int {
- switch cipher {
- case CipherCAST5:
- return cast5.KeySize
- case CipherAES128:
- return 16
- case CipherAES192:
- return 24
- case CipherAES256:
- return 32
- }
- return 0
-}
-
-// blockSize returns the block size, in bytes, of cipher.
-func (cipher CipherFunction) blockSize() int {
- switch cipher {
- case CipherCAST5:
- return 8
- case CipherAES128, CipherAES192, CipherAES256:
- return 16
- }
- return 0
-}
-
-// new returns a fresh instance of the given cipher.
-func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
- switch cipher {
- case CipherCAST5:
- block, _ = cast5.NewCipher(key)
- case CipherAES128, CipherAES192, CipherAES256:
- block, _ = aes.NewCipher(key)
- }
- return
-}
-
-// readMPI reads a big integer from r. The bit length returned is the bit
-// length that was specified in r. This is preserved so that the integer can be
-// reserialized exactly.
-func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
- var buf [2]byte
- _, err = readFull(r, buf[0:])
- if err != nil {
- return
- }
- bitLength = uint16(buf[0])<<8 | uint16(buf[1])
- numBytes := (int(bitLength) + 7) / 8
- mpi = make([]byte, numBytes)
- _, err = readFull(r, mpi)
- return
-}
-
-// mpiLength returns the length of the given *big.Int when serialized as an
-// MPI.
-func mpiLength(n *big.Int) (mpiLengthInBytes int) {
- mpiLengthInBytes = 2 /* MPI length */
- mpiLengthInBytes += (n.BitLen() + 7) / 8
- return
-}
-
-// writeMPI serializes a big integer to w.
-func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
- _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
- if err == nil {
- _, err = w.Write(mpiBytes)
- }
- return
-}
-
-// writeBig serializes a *big.Int to w.
-func writeBig(w io.Writer, i *big.Int) error {
- return writeMPI(w, uint16(i.BitLen()), i.Bytes())
-}
diff --git a/libgo/go/crypto/openpgp/packet/packet_test.go b/libgo/go/crypto/openpgp/packet/packet_test.go
deleted file mode 100644
index e4b86914192..00000000000
--- a/libgo/go/crypto/openpgp/packet/packet_test.go
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto/openpgp/errors"
- "encoding/hex"
- "fmt"
- "io"
- "io/ioutil"
- "testing"
-)
-
-func TestReadFull(t *testing.T) {
- var out [4]byte
-
- b := bytes.NewBufferString("foo")
- n, err := readFull(b, out[:3])
- if n != 3 || err != nil {
- t.Errorf("full read failed n:%d err:%s", n, err)
- }
-
- b = bytes.NewBufferString("foo")
- n, err = readFull(b, out[:4])
- if n != 3 || err != io.ErrUnexpectedEOF {
- t.Errorf("partial read failed n:%d err:%s", n, err)
- }
-
- b = bytes.NewBuffer(nil)
- n, err = readFull(b, out[:3])
- if n != 0 || err != io.ErrUnexpectedEOF {
- t.Errorf("empty read failed n:%d err:%s", n, err)
- }
-}
-
-func readerFromHex(s string) io.Reader {
- data, err := hex.DecodeString(s)
- if err != nil {
- panic("readerFromHex: bad input")
- }
- return bytes.NewBuffer(data)
-}
-
-var readLengthTests = []struct {
- hexInput string
- length int64
- isPartial bool
- err error
-}{
- {"", 0, false, io.ErrUnexpectedEOF},
- {"1f", 31, false, nil},
- {"c0", 0, false, io.ErrUnexpectedEOF},
- {"c101", 256 + 1 + 192, false, nil},
- {"e0", 1, true, nil},
- {"e1", 2, true, nil},
- {"e2", 4, true, nil},
- {"ff", 0, false, io.ErrUnexpectedEOF},
- {"ff00", 0, false, io.ErrUnexpectedEOF},
- {"ff0000", 0, false, io.ErrUnexpectedEOF},
- {"ff000000", 0, false, io.ErrUnexpectedEOF},
- {"ff00000000", 0, false, nil},
- {"ff01020304", 16909060, false, nil},
-}
-
-func TestReadLength(t *testing.T) {
- for i, test := range readLengthTests {
- length, isPartial, err := readLength(readerFromHex(test.hexInput))
- if test.err != nil {
- if err != test.err {
- t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
- }
- continue
- }
- if err != nil {
- t.Errorf("%d: unexpected error: %s", i, err)
- continue
- }
- if length != test.length || isPartial != test.isPartial {
- t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
- }
- }
-}
-
-var partialLengthReaderTests = []struct {
- hexInput string
- err error
- hexOutput string
-}{
- {"e0", io.ErrUnexpectedEOF, ""},
- {"e001", io.ErrUnexpectedEOF, ""},
- {"e0010102", nil, "0102"},
- {"ff00000000", nil, ""},
- {"e10102e1030400", nil, "01020304"},
- {"e101", io.ErrUnexpectedEOF, ""},
-}
-
-func TestPartialLengthReader(t *testing.T) {
- for i, test := range partialLengthReaderTests {
- r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
- out, err := ioutil.ReadAll(r)
- if test.err != nil {
- if err != test.err {
- t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
- }
- continue
- }
- if err != nil {
- t.Errorf("%d: unexpected error: %s", i, err)
- continue
- }
-
- got := fmt.Sprintf("%x", out)
- if got != test.hexOutput {
- t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
- }
- }
-}
-
-var readHeaderTests = []struct {
- hexInput string
- structuralError bool
- unexpectedEOF bool
- tag int
- length int64
- hexOutput string
-}{
- {"", false, false, 0, 0, ""},
- {"7f", true, false, 0, 0, ""},
-
- // Old format headers
- {"80", false, true, 0, 0, ""},
- {"8001", false, true, 0, 1, ""},
- {"800102", false, false, 0, 1, "02"},
- {"81000102", false, false, 0, 1, "02"},
- {"820000000102", false, false, 0, 1, "02"},
- {"860000000102", false, false, 1, 1, "02"},
- {"83010203", false, false, 0, -1, "010203"},
-
- // New format headers
- {"c0", false, true, 0, 0, ""},
- {"c000", false, false, 0, 0, ""},
- {"c00102", false, false, 0, 1, "02"},
- {"c0020203", false, false, 0, 2, "0203"},
- {"c00202", false, true, 0, 2, ""},
- {"c3020203", false, false, 3, 2, "0203"},
-}
-
-func TestReadHeader(t *testing.T) {
- for i, test := range readHeaderTests {
- tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
- if test.structuralError {
- if _, ok := err.(errors.StructuralError); ok {
- continue
- }
- t.Errorf("%d: expected StructuralError, got:%s", i, err)
- continue
- }
- if err != nil {
- if len(test.hexInput) == 0 && err == io.EOF {
- continue
- }
- if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
- t.Errorf("%d: unexpected error from readHeader: %s", i, err)
- }
- continue
- }
- if int(tag) != test.tag || length != test.length {
- t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
- continue
- }
-
- body, err := ioutil.ReadAll(contents)
- if err != nil {
- if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
- t.Errorf("%d: unexpected error from contents: %s", i, err)
- }
- continue
- }
- if test.unexpectedEOF {
- t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
- continue
- }
- got := fmt.Sprintf("%x", body)
- if got != test.hexOutput {
- t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
- }
- }
-}
-
-func TestSerializeHeader(t *testing.T) {
- tag := packetTypePublicKey
- lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
-
- for _, length := range lengths {
- buf := bytes.NewBuffer(nil)
- serializeHeader(buf, tag, length)
- tag2, length2, _, err := readHeader(buf)
- if err != nil {
- t.Errorf("length %d, err: %s", length, err)
- }
- if tag2 != tag {
- t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
- }
- if int(length2) != length {
- t.Errorf("length %d, length incorrect (got %d)", length, length2)
- }
- }
-}
-
-func TestPartialLengths(t *testing.T) {
- buf := bytes.NewBuffer(nil)
- w := new(partialLengthWriter)
- w.w = noOpCloser{buf}
-
- const maxChunkSize = 64
-
- var b [maxChunkSize]byte
- var n uint8
- for l := 1; l <= maxChunkSize; l++ {
- for i := 0; i < l; i++ {
- b[i] = n
- n++
- }
- m, err := w.Write(b[:l])
- if m != l {
- t.Errorf("short write got: %d want: %d", m, l)
- }
- if err != nil {
- t.Errorf("error from write: %s", err)
- }
- }
- w.Close()
-
- want := (maxChunkSize * (maxChunkSize + 1)) / 2
- copyBuf := bytes.NewBuffer(nil)
- r := &partialLengthReader{buf, 0, true}
- m, err := io.Copy(copyBuf, r)
- if m != int64(want) {
- t.Errorf("short copy got: %d want: %d", m, want)
- }
- if err != nil {
- t.Errorf("error from copy: %s", err)
- }
-
- copyBytes := copyBuf.Bytes()
- for i := 0; i < want; i++ {
- if copyBytes[i] != uint8(i) {
- t.Errorf("bad pattern in copy at %d", i)
- break
- }
- }
-}
diff --git a/libgo/go/crypto/openpgp/packet/private_key.go b/libgo/go/crypto/openpgp/packet/private_key.go
deleted file mode 100644
index 5a90d0625fa..00000000000
--- a/libgo/go/crypto/openpgp/packet/private_key.go
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto/cipher"
- "crypto/dsa"
- "crypto/openpgp/elgamal"
- "crypto/openpgp/errors"
- "crypto/openpgp/s2k"
- "crypto/rsa"
- "crypto/sha1"
- "io"
- "io/ioutil"
- "math/big"
- "strconv"
- "time"
-)
-
-// PrivateKey represents a possibly encrypted private key. See RFC 4880,
-// section 5.5.3.
-type PrivateKey struct {
- PublicKey
- Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
- encryptedData []byte
- cipher CipherFunction
- s2k func(out, in []byte)
- PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
- sha1Checksum bool
- iv []byte
-}
-
-func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
- pk := new(PrivateKey)
- pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
- pk.PrivateKey = priv
- return pk
-}
-
-func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
- pk := new(PrivateKey)
- pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
- pk.PrivateKey = priv
- return pk
-}
-
-func (pk *PrivateKey) parse(r io.Reader) (err error) {
- err = (&pk.PublicKey).parse(r)
- if err != nil {
- return
- }
- var buf [1]byte
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
-
- s2kType := buf[0]
-
- switch s2kType {
- case 0:
- pk.s2k = nil
- pk.Encrypted = false
- case 254, 255:
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
- pk.cipher = CipherFunction(buf[0])
- pk.Encrypted = true
- pk.s2k, err = s2k.Parse(r)
- if err != nil {
- return
- }
- if s2kType == 254 {
- pk.sha1Checksum = true
- }
- default:
- return errors.UnsupportedError("deprecated s2k function in private key")
- }
-
- if pk.Encrypted {
- blockSize := pk.cipher.blockSize()
- if blockSize == 0 {
- return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
- }
- pk.iv = make([]byte, blockSize)
- _, err = readFull(r, pk.iv)
- if err != nil {
- return
- }
- }
-
- pk.encryptedData, err = ioutil.ReadAll(r)
- if err != nil {
- return
- }
-
- if !pk.Encrypted {
- return pk.parsePrivateKey(pk.encryptedData)
- }
-
- return
-}
-
-func mod64kHash(d []byte) uint16 {
- var h uint16
- for _, b := range d {
- h += uint16(b)
- }
- return h
-}
-
-func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
- // TODO(agl): support encrypted private keys
- buf := bytes.NewBuffer(nil)
- err = pk.PublicKey.serializeWithoutHeaders(buf)
- if err != nil {
- return
- }
- buf.WriteByte(0 /* no encryption */ )
-
- privateKeyBuf := bytes.NewBuffer(nil)
-
- switch priv := pk.PrivateKey.(type) {
- case *rsa.PrivateKey:
- err = serializeRSAPrivateKey(privateKeyBuf, priv)
- case *dsa.PrivateKey:
- err = serializeDSAPrivateKey(privateKeyBuf, priv)
- default:
- err = errors.InvalidArgumentError("unknown private key type")
- }
- if err != nil {
- return
- }
-
- ptype := packetTypePrivateKey
- contents := buf.Bytes()
- privateKeyBytes := privateKeyBuf.Bytes()
- if pk.IsSubkey {
- ptype = packetTypePrivateSubkey
- }
- err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
- if err != nil {
- return
- }
- _, err = w.Write(contents)
- if err != nil {
- return
- }
- _, err = w.Write(privateKeyBytes)
- if err != nil {
- return
- }
-
- checksum := mod64kHash(privateKeyBytes)
- var checksumBytes [2]byte
- checksumBytes[0] = byte(checksum >> 8)
- checksumBytes[1] = byte(checksum)
- _, err = w.Write(checksumBytes[:])
-
- return
-}
-
-func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
- err := writeBig(w, priv.D)
- if err != nil {
- return err
- }
- err = writeBig(w, priv.Primes[1])
- if err != nil {
- return err
- }
- err = writeBig(w, priv.Primes[0])
- if err != nil {
- return err
- }
- return writeBig(w, priv.Precomputed.Qinv)
-}
-
-func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
- return writeBig(w, priv.X)
-}
-
-// Decrypt decrypts an encrypted private key using a passphrase.
-func (pk *PrivateKey) Decrypt(passphrase []byte) error {
- if !pk.Encrypted {
- return nil
- }
-
- key := make([]byte, pk.cipher.KeySize())
- pk.s2k(key, passphrase)
- block := pk.cipher.new(key)
- cfb := cipher.NewCFBDecrypter(block, pk.iv)
-
- data := pk.encryptedData
- cfb.XORKeyStream(data, data)
-
- if pk.sha1Checksum {
- if len(data) < sha1.Size {
- return errors.StructuralError("truncated private key data")
- }
- h := sha1.New()
- h.Write(data[:len(data)-sha1.Size])
- sum := h.Sum(nil)
- if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
- return errors.StructuralError("private key checksum failure")
- }
- data = data[:len(data)-sha1.Size]
- } else {
- if len(data) < 2 {
- return errors.StructuralError("truncated private key data")
- }
- var sum uint16
- for i := 0; i < len(data)-2; i++ {
- sum += uint16(data[i])
- }
- if data[len(data)-2] != uint8(sum>>8) ||
- data[len(data)-1] != uint8(sum) {
- return errors.StructuralError("private key checksum failure")
- }
- data = data[:len(data)-2]
- }
-
- return pk.parsePrivateKey(data)
-}
-
-func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
- switch pk.PublicKey.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
- return pk.parseRSAPrivateKey(data)
- case PubKeyAlgoDSA:
- return pk.parseDSAPrivateKey(data)
- case PubKeyAlgoElGamal:
- return pk.parseElGamalPrivateKey(data)
- }
- panic("impossible")
-}
-
-func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
- rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
- rsaPriv := new(rsa.PrivateKey)
- rsaPriv.PublicKey = *rsaPub
-
- buf := bytes.NewBuffer(data)
- d, _, err := readMPI(buf)
- if err != nil {
- return
- }
- p, _, err := readMPI(buf)
- if err != nil {
- return
- }
- q, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- rsaPriv.D = new(big.Int).SetBytes(d)
- rsaPriv.Primes = make([]*big.Int, 2)
- rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
- rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
- rsaPriv.Precompute()
- pk.PrivateKey = rsaPriv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
-}
-
-func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
- dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
- dsaPriv := new(dsa.PrivateKey)
- dsaPriv.PublicKey = *dsaPub
-
- buf := bytes.NewBuffer(data)
- x, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- dsaPriv.X = new(big.Int).SetBytes(x)
- pk.PrivateKey = dsaPriv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
-}
-
-func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
- pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
- priv := new(elgamal.PrivateKey)
- priv.PublicKey = *pub
-
- buf := bytes.NewBuffer(data)
- x, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- priv.X = new(big.Int).SetBytes(x)
- pk.PrivateKey = priv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
-}
diff --git a/libgo/go/crypto/openpgp/packet/private_key_test.go b/libgo/go/crypto/openpgp/packet/private_key_test.go
deleted file mode 100644
index 35d8951a86b..00000000000
--- a/libgo/go/crypto/openpgp/packet/private_key_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "testing"
- "time"
-)
-
-var privateKeyTests = []struct {
- privateKeyHex string
- creationTime time.Time
-}{
- {
- privKeyRSAHex,
- time.Unix(0x4cc349a8, 0),
- },
- {
- privKeyElGamalHex,
- time.Unix(0x4df9ee1a, 0),
- },
-}
-
-func TestPrivateKeyRead(t *testing.T) {
- for i, test := range privateKeyTests {
- packet, err := Read(readerFromHex(test.privateKeyHex))
- if err != nil {
- t.Errorf("#%d: failed to parse: %s", i, err)
- continue
- }
-
- privKey := packet.(*PrivateKey)
-
- if !privKey.Encrypted {
- t.Errorf("#%d: private key isn't encrypted", i)
- continue
- }
-
- err = privKey.Decrypt([]byte("testing"))
- if err != nil {
- t.Errorf("#%d: failed to decrypt: %s", i, err)
- continue
- }
-
- if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted {
- t.Errorf("#%d: bad result, got: %#v", i, privKey)
- }
- }
-}
-
-// Generated with `gpg --export-secret-keys "Test Key 2"`
-const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
-
-// Generated by `gpg --export-secret-keys` followed by a manual extraction of
-// the ElGamal subkey from the packets.
-const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
diff --git a/libgo/go/crypto/openpgp/packet/public_key.go b/libgo/go/crypto/openpgp/packet/public_key.go
deleted file mode 100644
index ba178b519eb..00000000000
--- a/libgo/go/crypto/openpgp/packet/public_key.go
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "crypto/dsa"
- "crypto/openpgp/elgamal"
- "crypto/openpgp/errors"
- "crypto/rsa"
- "crypto/sha1"
- "encoding/binary"
- "fmt"
- "hash"
- "io"
- "math/big"
- "strconv"
- "time"
-)
-
-// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
-type PublicKey struct {
- CreationTime time.Time
- PubKeyAlgo PublicKeyAlgorithm
- PublicKey interface{} // Either a *rsa.PublicKey or *dsa.PublicKey
- Fingerprint [20]byte
- KeyId uint64
- IsSubkey bool
-
- n, e, p, q, g, y parsedMPI
-}
-
-func fromBig(n *big.Int) parsedMPI {
- return parsedMPI{
- bytes: n.Bytes(),
- bitLength: uint16(n.BitLen()),
- }
-}
-
-// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
-func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
- pk := &PublicKey{
- CreationTime: creationTime,
- PubKeyAlgo: PubKeyAlgoRSA,
- PublicKey: pub,
- n: fromBig(pub.N),
- e: fromBig(big.NewInt(int64(pub.E))),
- }
-
- pk.setFingerPrintAndKeyId()
- return pk
-}
-
-// NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
-func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
- pk := &PublicKey{
- CreationTime: creationTime,
- PubKeyAlgo: PubKeyAlgoDSA,
- PublicKey: pub,
- p: fromBig(pub.P),
- q: fromBig(pub.Q),
- g: fromBig(pub.G),
- y: fromBig(pub.Y),
- }
-
- pk.setFingerPrintAndKeyId()
- return pk
-}
-
-func (pk *PublicKey) parse(r io.Reader) (err error) {
- // RFC 4880, section 5.5.2
- var buf [6]byte
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
- if buf[0] != 4 {
- return errors.UnsupportedError("public key version")
- }
- pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
- pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
- switch pk.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
- err = pk.parseRSA(r)
- case PubKeyAlgoDSA:
- err = pk.parseDSA(r)
- case PubKeyAlgoElGamal:
- err = pk.parseElGamal(r)
- default:
- err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
- }
- if err != nil {
- return
- }
-
- pk.setFingerPrintAndKeyId()
- return
-}
-
-func (pk *PublicKey) setFingerPrintAndKeyId() {
- // RFC 4880, section 12.2
- fingerPrint := sha1.New()
- pk.SerializeSignaturePrefix(fingerPrint)
- pk.serializeWithoutHeaders(fingerPrint)
- copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
- pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
-}
-
-// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
-// section 5.5.2.
-func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
- pk.n.bytes, pk.n.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
- pk.e.bytes, pk.e.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
-
- if len(pk.e.bytes) > 3 {
- err = errors.UnsupportedError("large public exponent")
- return
- }
- rsa := &rsa.PublicKey{
- N: new(big.Int).SetBytes(pk.n.bytes),
- E: 0,
- }
- for i := 0; i < len(pk.e.bytes); i++ {
- rsa.E <<= 8
- rsa.E |= int(pk.e.bytes[i])
- }
- pk.PublicKey = rsa
- return
-}
-
-// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
-// section 5.5.2.
-func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
- pk.p.bytes, pk.p.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
- pk.q.bytes, pk.q.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
- pk.g.bytes, pk.g.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
- pk.y.bytes, pk.y.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
-
- dsa := new(dsa.PublicKey)
- dsa.P = new(big.Int).SetBytes(pk.p.bytes)
- dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
- dsa.G = new(big.Int).SetBytes(pk.g.bytes)
- dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
- pk.PublicKey = dsa
- return
-}
-
-// parseElGamal parses ElGamal public key material from the given Reader. See
-// RFC 4880, section 5.5.2.
-func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
- pk.p.bytes, pk.p.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
- pk.g.bytes, pk.g.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
- pk.y.bytes, pk.y.bitLength, err = readMPI(r)
- if err != nil {
- return
- }
-
- elgamal := new(elgamal.PublicKey)
- elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
- elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
- elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
- pk.PublicKey = elgamal
- return
-}
-
-// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
-// The prefix is used when calculating a signature over this public key. See
-// RFC 4880, section 5.2.4.
-func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
- var pLength uint16
- switch pk.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
- pLength += 2 + uint16(len(pk.n.bytes))
- pLength += 2 + uint16(len(pk.e.bytes))
- case PubKeyAlgoDSA:
- pLength += 2 + uint16(len(pk.p.bytes))
- pLength += 2 + uint16(len(pk.q.bytes))
- pLength += 2 + uint16(len(pk.g.bytes))
- pLength += 2 + uint16(len(pk.y.bytes))
- case PubKeyAlgoElGamal:
- pLength += 2 + uint16(len(pk.p.bytes))
- pLength += 2 + uint16(len(pk.g.bytes))
- pLength += 2 + uint16(len(pk.y.bytes))
- default:
- panic("unknown public key algorithm")
- }
- pLength += 6
- h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
- return
-}
-
-func (pk *PublicKey) Serialize(w io.Writer) (err error) {
- length := 6 // 6 byte header
-
- switch pk.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
- length += 2 + len(pk.n.bytes)
- length += 2 + len(pk.e.bytes)
- case PubKeyAlgoDSA:
- length += 2 + len(pk.p.bytes)
- length += 2 + len(pk.q.bytes)
- length += 2 + len(pk.g.bytes)
- length += 2 + len(pk.y.bytes)
- case PubKeyAlgoElGamal:
- length += 2 + len(pk.p.bytes)
- length += 2 + len(pk.g.bytes)
- length += 2 + len(pk.y.bytes)
- default:
- panic("unknown public key algorithm")
- }
-
- packetType := packetTypePublicKey
- if pk.IsSubkey {
- packetType = packetTypePublicSubkey
- }
- err = serializeHeader(w, packetType, length)
- if err != nil {
- return
- }
- return pk.serializeWithoutHeaders(w)
-}
-
-// serializeWithoutHeaders marshals the PublicKey to w in the form of an
-// OpenPGP public key packet, not including the packet header.
-func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
- var buf [6]byte
- buf[0] = 4
- t := uint32(pk.CreationTime.Unix())
- buf[1] = byte(t >> 24)
- buf[2] = byte(t >> 16)
- buf[3] = byte(t >> 8)
- buf[4] = byte(t)
- buf[5] = byte(pk.PubKeyAlgo)
-
- _, err = w.Write(buf[:])
- if err != nil {
- return
- }
-
- switch pk.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
- return writeMPIs(w, pk.n, pk.e)
- case PubKeyAlgoDSA:
- return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
- case PubKeyAlgoElGamal:
- return writeMPIs(w, pk.p, pk.g, pk.y)
- }
- return errors.InvalidArgumentError("bad public-key algorithm")
-}
-
-// CanSign returns true iff this public key can generate signatures
-func (pk *PublicKey) CanSign() bool {
- return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
-}
-
-// VerifySignature returns nil iff sig is a valid signature, made by this
-// public key, of the data hashed into signed. signed is mutated by this call.
-func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
- if !pk.CanSign() {
- return errors.InvalidArgumentError("public key cannot generate signatures")
- }
-
- signed.Write(sig.HashSuffix)
- hashBytes := signed.Sum(nil)
-
- if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
- return errors.SignatureError("hash tag doesn't match")
- }
-
- if pk.PubKeyAlgo != sig.PubKeyAlgo {
- return errors.InvalidArgumentError("public key and signature use different algorithms")
- }
-
- switch pk.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
- rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
- err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
- if err != nil {
- return errors.SignatureError("RSA verification failure")
- }
- return nil
- case PubKeyAlgoDSA:
- dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
- // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
- subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
- if len(hashBytes) > subgroupSize {
- hashBytes = hashBytes[:subgroupSize]
- }
- if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
- return errors.SignatureError("DSA verification failure")
- }
- return nil
- default:
- panic("shouldn't happen")
- }
- panic("unreachable")
-}
-
-// keySignatureHash returns a Hash of the message that needs to be signed for
-// pk to assert a subkey relationship to signed.
-func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err error) {
- h = sig.Hash.New()
- if h == nil {
- return nil, errors.UnsupportedError("hash function")
- }
-
- // RFC 4880, section 5.2.4
- pk.SerializeSignaturePrefix(h)
- pk.serializeWithoutHeaders(h)
- signed.SerializeSignaturePrefix(h)
- signed.serializeWithoutHeaders(h)
- return
-}
-
-// VerifyKeySignature returns nil iff sig is a valid signature, made by this
-// public key, of signed.
-func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) {
- h, err := keySignatureHash(pk, signed, sig)
- if err != nil {
- return err
- }
- return pk.VerifySignature(h, sig)
-}
-
-// userIdSignatureHash returns a Hash of the message that needs to be signed
-// to assert that pk is a valid key for id.
-func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err error) {
- h = sig.Hash.New()
- if h == nil {
- return nil, errors.UnsupportedError("hash function")
- }
-
- // RFC 4880, section 5.2.4
- pk.SerializeSignaturePrefix(h)
- pk.serializeWithoutHeaders(h)
-
- var buf [5]byte
- buf[0] = 0xb4
- buf[1] = byte(len(id) >> 24)
- buf[2] = byte(len(id) >> 16)
- buf[3] = byte(len(id) >> 8)
- buf[4] = byte(len(id))
- h.Write(buf[:])
- h.Write([]byte(id))
-
- return
-}
-
-// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
-// public key, of id.
-func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err error) {
- h, err := userIdSignatureHash(id, pk, sig)
- if err != nil {
- return err
- }
- return pk.VerifySignature(h, sig)
-}
-
-// KeyIdString returns the public key's fingerprint in capital hex
-// (e.g. "6C7EE1B8621CC013").
-func (pk *PublicKey) KeyIdString() string {
- return fmt.Sprintf("%X", pk.Fingerprint[12:20])
-}
-
-// KeyIdShortString returns the short form of public key's fingerprint
-// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
-func (pk *PublicKey) KeyIdShortString() string {
- return fmt.Sprintf("%X", pk.Fingerprint[16:20])
-}
-
-// A parsedMPI is used to store the contents of a big integer, along with the
-// bit length that was specified in the original input. This allows the MPI to
-// be reserialized exactly.
-type parsedMPI struct {
- bytes []byte
- bitLength uint16
-}
-
-// writeMPIs is a utility function for serializing several big integers to the
-// given Writer.
-func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
- for _, mpi := range mpis {
- err = writeMPI(w, mpi.bitLength, mpi.bytes)
- if err != nil {
- return
- }
- }
- return
-}
diff --git a/libgo/go/crypto/openpgp/packet/public_key_test.go b/libgo/go/crypto/openpgp/packet/public_key_test.go
deleted file mode 100644
index 72f459f47bf..00000000000
--- a/libgo/go/crypto/openpgp/packet/public_key_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "encoding/hex"
- "testing"
- "time"
-)
-
-var pubKeyTests = []struct {
- hexData string
- hexFingerprint string
- creationTime time.Time
- pubKeyAlgo PublicKeyAlgorithm
- keyId uint64
- keyIdString string
- keyIdShort string
-}{
- {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
- {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
-}
-
-func TestPublicKeyRead(t *testing.T) {
- for i, test := range pubKeyTests {
- packet, err := Read(readerFromHex(test.hexData))
- if err != nil {
- t.Errorf("#%d: Read error: %s", i, err)
- continue
- }
- pk, ok := packet.(*PublicKey)
- if !ok {
- t.Errorf("#%d: failed to parse, got: %#v", i, packet)
- continue
- }
- if pk.PubKeyAlgo != test.pubKeyAlgo {
- t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
- }
- if !pk.CreationTime.Equal(test.creationTime) {
- t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
- }
- expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
- if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
- t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
- }
- if pk.KeyId != test.keyId {
- t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
- }
- if g, e := pk.KeyIdString(), test.keyIdString; g != e {
- t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
- }
- if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
- t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
- }
- }
-}
-
-func TestPublicKeySerialize(t *testing.T) {
- for i, test := range pubKeyTests {
- packet, err := Read(readerFromHex(test.hexData))
- if err != nil {
- t.Errorf("#%d: Read error: %s", i, err)
- continue
- }
- pk, ok := packet.(*PublicKey)
- if !ok {
- t.Errorf("#%d: failed to parse, got: %#v", i, packet)
- continue
- }
- serializeBuf := bytes.NewBuffer(nil)
- err = pk.Serialize(serializeBuf)
- if err != nil {
- t.Errorf("#%d: failed to serialize: %s", i, err)
- continue
- }
-
- packet, err = Read(serializeBuf)
- if err != nil {
- t.Errorf("#%d: Read error (from serialized data): %s", i, err)
- continue
- }
- pk, ok = packet.(*PublicKey)
- if !ok {
- t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
- continue
- }
- }
-}
-
-const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
-
-const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
-
-const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
-
-const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
diff --git a/libgo/go/crypto/openpgp/packet/reader.go b/libgo/go/crypto/openpgp/packet/reader.go
deleted file mode 100644
index 1a3e8e23133..00000000000
--- a/libgo/go/crypto/openpgp/packet/reader.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "crypto/openpgp/errors"
- "io"
-)
-
-// Reader reads packets from an io.Reader and allows packets to be 'unread' so
-// that they result from the next call to Next.
-type Reader struct {
- q []Packet
- readers []io.Reader
-}
-
-// Next returns the most recently unread Packet, or reads another packet from
-// the top-most io.Reader. Unknown packet types are skipped.
-func (r *Reader) Next() (p Packet, err error) {
- if len(r.q) > 0 {
- p = r.q[len(r.q)-1]
- r.q = r.q[:len(r.q)-1]
- return
- }
-
- for len(r.readers) > 0 {
- p, err = Read(r.readers[len(r.readers)-1])
- if err == nil {
- return
- }
- if err == io.EOF {
- r.readers = r.readers[:len(r.readers)-1]
- continue
- }
- if _, ok := err.(errors.UnknownPacketTypeError); !ok {
- return nil, err
- }
- }
-
- return nil, io.EOF
-}
-
-// Push causes the Reader to start reading from a new io.Reader. When an EOF
-// error is seen from the new io.Reader, it is popped and the Reader continues
-// to read from the next most recent io.Reader.
-func (r *Reader) Push(reader io.Reader) {
- r.readers = append(r.readers, reader)
-}
-
-// Unread causes the given Packet to be returned from the next call to Next.
-func (r *Reader) Unread(p Packet) {
- r.q = append(r.q, p)
-}
-
-func NewReader(r io.Reader) *Reader {
- return &Reader{
- q: nil,
- readers: []io.Reader{r},
- }
-}
diff --git a/libgo/go/crypto/openpgp/packet/signature.go b/libgo/go/crypto/openpgp/packet/signature.go
deleted file mode 100644
index c3ffb3a6fb9..00000000000
--- a/libgo/go/crypto/openpgp/packet/signature.go
+++ /dev/null
@@ -1,611 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "crypto"
- "crypto/dsa"
- "crypto/openpgp/errors"
- "crypto/openpgp/s2k"
- "crypto/rsa"
- "encoding/binary"
- "hash"
- "io"
- "strconv"
- "time"
-)
-
-// Signature represents a signature. See RFC 4880, section 5.2.
-type Signature struct {
- SigType SignatureType
- PubKeyAlgo PublicKeyAlgorithm
- Hash crypto.Hash
-
- // HashSuffix is extra data that is hashed in after the signed data.
- HashSuffix []byte
- // HashTag contains the first two bytes of the hash for fast rejection
- // of bad signed data.
- HashTag [2]byte
- CreationTime time.Time
-
- RSASignature parsedMPI
- DSASigR, DSASigS parsedMPI
-
- // rawSubpackets contains the unparsed subpackets, in order.
- rawSubpackets []outputSubpacket
-
- // The following are optional so are nil when not included in the
- // signature.
-
- SigLifetimeSecs, KeyLifetimeSecs *uint32
- PreferredSymmetric, PreferredHash, PreferredCompression []uint8
- IssuerKeyId *uint64
- IsPrimaryId *bool
-
- // FlagsValid is set if any flags were given. See RFC 4880, section
- // 5.2.3.21 for details.
- FlagsValid bool
- FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
-
- outSubpackets []outputSubpacket
-}
-
-func (sig *Signature) parse(r io.Reader) (err error) {
- // RFC 4880, section 5.2.3
- var buf [5]byte
- _, err = readFull(r, buf[:1])
- if err != nil {
- return
- }
- if buf[0] != 4 {
- err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
- return
- }
-
- _, err = readFull(r, buf[:5])
- if err != nil {
- return
- }
- sig.SigType = SignatureType(buf[0])
- sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
- switch sig.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
- default:
- err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
- return
- }
-
- var ok bool
- sig.Hash, ok = s2k.HashIdToHash(buf[2])
- if !ok {
- return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
- }
-
- hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
- l := 6 + hashedSubpacketsLength
- sig.HashSuffix = make([]byte, l+6)
- sig.HashSuffix[0] = 4
- copy(sig.HashSuffix[1:], buf[:5])
- hashedSubpackets := sig.HashSuffix[6:l]
- _, err = readFull(r, hashedSubpackets)
- if err != nil {
- return
- }
- // See RFC 4880, section 5.2.4
- trailer := sig.HashSuffix[l:]
- trailer[0] = 4
- trailer[1] = 0xff
- trailer[2] = uint8(l >> 24)
- trailer[3] = uint8(l >> 16)
- trailer[4] = uint8(l >> 8)
- trailer[5] = uint8(l)
-
- err = parseSignatureSubpackets(sig, hashedSubpackets, true)
- if err != nil {
- return
- }
-
- _, err = readFull(r, buf[:2])
- if err != nil {
- return
- }
- unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
- unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
- _, err = readFull(r, unhashedSubpackets)
- if err != nil {
- return
- }
- err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
- if err != nil {
- return
- }
-
- _, err = readFull(r, sig.HashTag[:2])
- if err != nil {
- return
- }
-
- switch sig.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
- sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
- case PubKeyAlgoDSA:
- sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
- if err == nil {
- sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
- }
- default:
- panic("unreachable")
- }
- return
-}
-
-// parseSignatureSubpackets parses subpackets of the main signature packet. See
-// RFC 4880, section 5.2.3.1.
-func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
- for len(subpackets) > 0 {
- subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
- if err != nil {
- return
- }
- }
-
- if sig.CreationTime.IsZero() {
- err = errors.StructuralError("no creation time in signature")
- }
-
- return
-}
-
-type signatureSubpacketType uint8
-
-const (
- creationTimeSubpacket signatureSubpacketType = 2
- signatureExpirationSubpacket signatureSubpacketType = 3
- keyExpirationSubpacket signatureSubpacketType = 9
- prefSymmetricAlgosSubpacket signatureSubpacketType = 11
- issuerSubpacket signatureSubpacketType = 16
- prefHashAlgosSubpacket signatureSubpacketType = 21
- prefCompressionSubpacket signatureSubpacketType = 22
- primaryUserIdSubpacket signatureSubpacketType = 25
- keyFlagsSubpacket signatureSubpacketType = 27
-)
-
-// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
-func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
- // RFC 4880, section 5.2.3.1
- var (
- length uint32
- packetType signatureSubpacketType
- isCritical bool
- )
- switch {
- case subpacket[0] < 192:
- length = uint32(subpacket[0])
- subpacket = subpacket[1:]
- case subpacket[0] < 255:
- if len(subpacket) < 2 {
- goto Truncated
- }
- length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
- subpacket = subpacket[2:]
- default:
- if len(subpacket) < 5 {
- goto Truncated
- }
- length = uint32(subpacket[1])<<24 |
- uint32(subpacket[2])<<16 |
- uint32(subpacket[3])<<8 |
- uint32(subpacket[4])
- subpacket = subpacket[5:]
- }
- if length > uint32(len(subpacket)) {
- goto Truncated
- }
- rest = subpacket[length:]
- subpacket = subpacket[:length]
- if len(subpacket) == 0 {
- err = errors.StructuralError("zero length signature subpacket")
- return
- }
- packetType = signatureSubpacketType(subpacket[0] & 0x7f)
- isCritical = subpacket[0]&0x80 == 0x80
- subpacket = subpacket[1:]
- sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
- switch packetType {
- case creationTimeSubpacket:
- if !isHashed {
- err = errors.StructuralError("signature creation time in non-hashed area")
- return
- }
- if len(subpacket) != 4 {
- err = errors.StructuralError("signature creation time not four bytes")
- return
- }
- t := binary.BigEndian.Uint32(subpacket)
- sig.CreationTime = time.Unix(int64(t), 0)
- case signatureExpirationSubpacket:
- // Signature expiration time, section 5.2.3.10
- if !isHashed {
- return
- }
- if len(subpacket) != 4 {
- err = errors.StructuralError("expiration subpacket with bad length")
- return
- }
- sig.SigLifetimeSecs = new(uint32)
- *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
- case keyExpirationSubpacket:
- // Key expiration time, section 5.2.3.6
- if !isHashed {
- return
- }
- if len(subpacket) != 4 {
- err = errors.StructuralError("key expiration subpacket with bad length")
- return
- }
- sig.KeyLifetimeSecs = new(uint32)
- *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
- case prefSymmetricAlgosSubpacket:
- // Preferred symmetric algorithms, section 5.2.3.7
- if !isHashed {
- return
- }
- sig.PreferredSymmetric = make([]byte, len(subpacket))
- copy(sig.PreferredSymmetric, subpacket)
- case issuerSubpacket:
- // Issuer, section 5.2.3.5
- if len(subpacket) != 8 {
- err = errors.StructuralError("issuer subpacket with bad length")
- return
- }
- sig.IssuerKeyId = new(uint64)
- *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
- case prefHashAlgosSubpacket:
- // Preferred hash algorithms, section 5.2.3.8
- if !isHashed {
- return
- }
- sig.PreferredHash = make([]byte, len(subpacket))
- copy(sig.PreferredHash, subpacket)
- case prefCompressionSubpacket:
- // Preferred compression algorithms, section 5.2.3.9
- if !isHashed {
- return
- }
- sig.PreferredCompression = make([]byte, len(subpacket))
- copy(sig.PreferredCompression, subpacket)
- case primaryUserIdSubpacket:
- // Primary User ID, section 5.2.3.19
- if !isHashed {
- return
- }
- if len(subpacket) != 1 {
- err = errors.StructuralError("primary user id subpacket with bad length")
- return
- }
- sig.IsPrimaryId = new(bool)
- if subpacket[0] > 0 {
- *sig.IsPrimaryId = true
- }
- case keyFlagsSubpacket:
- // Key flags, section 5.2.3.21
- if !isHashed {
- return
- }
- if len(subpacket) == 0 {
- err = errors.StructuralError("empty key flags subpacket")
- return
- }
- sig.FlagsValid = true
- if subpacket[0]&1 != 0 {
- sig.FlagCertify = true
- }
- if subpacket[0]&2 != 0 {
- sig.FlagSign = true
- }
- if subpacket[0]&4 != 0 {
- sig.FlagEncryptCommunications = true
- }
- if subpacket[0]&8 != 0 {
- sig.FlagEncryptStorage = true
- }
-
- default:
- if isCritical {
- err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
- return
- }
- }
- return
-
-Truncated:
- err = errors.StructuralError("signature subpacket truncated")
- return
-}
-
-// subpacketLengthLength returns the length, in bytes, of an encoded length value.
-func subpacketLengthLength(length int) int {
- if length < 192 {
- return 1
- }
- if length < 16320 {
- return 2
- }
- return 5
-}
-
-// serializeSubpacketLength marshals the given length into to.
-func serializeSubpacketLength(to []byte, length int) int {
- if length < 192 {
- to[0] = byte(length)
- return 1
- }
- if length < 16320 {
- length -= 192
- to[0] = byte(length >> 8)
- to[1] = byte(length)
- return 2
- }
- to[0] = 255
- to[1] = byte(length >> 24)
- to[2] = byte(length >> 16)
- to[3] = byte(length >> 8)
- to[4] = byte(length)
- return 5
-}
-
-// subpacketsLength returns the serialized length, in bytes, of the given
-// subpackets.
-func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
- for _, subpacket := range subpackets {
- if subpacket.hashed == hashed {
- length += subpacketLengthLength(len(subpacket.contents) + 1)
- length += 1 // type byte
- length += len(subpacket.contents)
- }
- }
- return
-}
-
-// serializeSubpackets marshals the given subpackets into to.
-func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
- for _, subpacket := range subpackets {
- if subpacket.hashed == hashed {
- n := serializeSubpacketLength(to, len(subpacket.contents)+1)
- to[n] = byte(subpacket.subpacketType)
- to = to[1+n:]
- n = copy(to, subpacket.contents)
- to = to[n:]
- }
- }
- return
-}
-
-// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
-func (sig *Signature) buildHashSuffix() (err error) {
- hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
-
- var ok bool
- l := 6 + hashedSubpacketsLen
- sig.HashSuffix = make([]byte, l+6)
- sig.HashSuffix[0] = 4
- sig.HashSuffix[1] = uint8(sig.SigType)
- sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
- sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
- if !ok {
- sig.HashSuffix = nil
- return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
- }
- sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
- sig.HashSuffix[5] = byte(hashedSubpacketsLen)
- serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
- trailer := sig.HashSuffix[l:]
- trailer[0] = 4
- trailer[1] = 0xff
- trailer[2] = byte(l >> 24)
- trailer[3] = byte(l >> 16)
- trailer[4] = byte(l >> 8)
- trailer[5] = byte(l)
- return
-}
-
-func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
- err = sig.buildHashSuffix()
- if err != nil {
- return
- }
-
- h.Write(sig.HashSuffix)
- digest = h.Sum(nil)
- copy(sig.HashTag[:], digest)
- return
-}
-
-// Sign signs a message with a private key. The hash, h, must contain
-// the hash of the message to be signed and will be mutated by this function.
-// On success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) {
- sig.outSubpackets = sig.buildSubpackets()
- digest, err := sig.signPrepareHash(h)
- if err != nil {
- return
- }
-
- switch priv.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
- sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
- sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
- case PubKeyAlgoDSA:
- dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
-
- // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
- subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
- if len(digest) > subgroupSize {
- digest = digest[:subgroupSize]
- }
- r, s, err := dsa.Sign(rand, dsaPriv, digest)
- if err == nil {
- sig.DSASigR.bytes = r.Bytes()
- sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
- sig.DSASigS.bytes = s.Bytes()
- sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
- }
- default:
- err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
- }
-
- return
-}
-
-// SignUserId computes a signature from priv, asserting that pub is a valid
-// key for the identity id. On success, the signature is stored in sig. Call
-// Serialize to write it out.
-func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error {
- h, err := userIdSignatureHash(id, pub, sig)
- if err != nil {
- return nil
- }
- return sig.Sign(rand, h, priv)
-}
-
-// SignKey computes a signature from priv, asserting that pub is a subkey. On
-// success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error {
- h, err := keySignatureHash(&priv.PublicKey, pub, sig)
- if err != nil {
- return err
- }
- return sig.Sign(rand, h, priv)
-}
-
-// Serialize marshals sig to w. SignRSA or SignDSA must have been called first.
-func (sig *Signature) Serialize(w io.Writer) (err error) {
- if len(sig.outSubpackets) == 0 {
- sig.outSubpackets = sig.rawSubpackets
- }
- if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
- return errors.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize")
- }
-
- sigLength := 0
- switch sig.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
- sigLength = 2 + len(sig.RSASignature.bytes)
- case PubKeyAlgoDSA:
- sigLength = 2 + len(sig.DSASigR.bytes)
- sigLength += 2 + len(sig.DSASigS.bytes)
- default:
- panic("impossible")
- }
-
- unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
- length := len(sig.HashSuffix) - 6 /* trailer not included */ +
- 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
- 2 /* hash tag */ + sigLength
- err = serializeHeader(w, packetTypeSignature, length)
- if err != nil {
- return
- }
-
- _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
- if err != nil {
- return
- }
-
- unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
- unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
- unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
- serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
-
- _, err = w.Write(unhashedSubpackets)
- if err != nil {
- return
- }
- _, err = w.Write(sig.HashTag[:])
- if err != nil {
- return
- }
-
- switch sig.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
- err = writeMPIs(w, sig.RSASignature)
- case PubKeyAlgoDSA:
- err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
- default:
- panic("impossible")
- }
- return
-}
-
-// outputSubpacket represents a subpacket to be marshaled.
-type outputSubpacket struct {
- hashed bool // true if this subpacket is in the hashed area.
- subpacketType signatureSubpacketType
- isCritical bool
- contents []byte
-}
-
-func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
- creationTime := make([]byte, 4)
- binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
- subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
-
- if sig.IssuerKeyId != nil {
- keyId := make([]byte, 8)
- binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
- subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
- }
-
- if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
- sigLifetime := make([]byte, 4)
- binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
- subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
- }
-
- // Key flags may only appear in self-signatures or certification signatures.
-
- if sig.FlagsValid {
- var flags byte
- if sig.FlagCertify {
- flags |= 1
- }
- if sig.FlagSign {
- flags |= 2
- }
- if sig.FlagEncryptCommunications {
- flags |= 4
- }
- if sig.FlagEncryptStorage {
- flags |= 8
- }
- subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
- }
-
- // The following subpackets may only appear in self-signatures
-
- if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
- keyLifetime := make([]byte, 4)
- binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
- subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
- }
-
- if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
- subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
- }
-
- if len(sig.PreferredSymmetric) > 0 {
- subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
- }
-
- if len(sig.PreferredHash) > 0 {
- subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
- }
-
- if len(sig.PreferredCompression) > 0 {
- subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
- }
-
- return
-}
diff --git a/libgo/go/crypto/openpgp/packet/signature_test.go b/libgo/go/crypto/openpgp/packet/signature_test.go
deleted file mode 100644
index c1bbde8b0c3..00000000000
--- a/libgo/go/crypto/openpgp/packet/signature_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto"
- "encoding/hex"
- "testing"
-)
-
-func TestSignatureRead(t *testing.T) {
- packet, err := Read(readerFromHex(signatureDataHex))
- if err != nil {
- t.Error(err)
- return
- }
- sig, ok := packet.(*Signature)
- if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
- t.Errorf("failed to parse, got: %#v", packet)
- }
-}
-
-func TestSignatureReserialize(t *testing.T) {
- packet, _ := Read(readerFromHex(signatureDataHex))
- sig := packet.(*Signature)
- out := new(bytes.Buffer)
- err := sig.Serialize(out)
- if err != nil {
- t.Errorf("error reserializing: %s", err)
- return
- }
-
- expected, _ := hex.DecodeString(signatureDataHex)
- if !bytes.Equal(expected, out.Bytes()) {
- t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
- }
-}
-
-const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
diff --git a/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go b/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go
deleted file mode 100644
index 94e07050401..00000000000
--- a/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto/cipher"
- "crypto/openpgp/errors"
- "crypto/openpgp/s2k"
- "io"
- "strconv"
-)
-
-// This is the largest session key that we'll support. Since no 512-bit cipher
-// has even been seriously used, this is comfortably large.
-const maxSessionKeySizeInBytes = 64
-
-// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
-// 4880, section 5.3.
-type SymmetricKeyEncrypted struct {
- CipherFunc CipherFunction
- Encrypted bool
- Key []byte // Empty unless Encrypted is false.
- s2k func(out, in []byte)
- encryptedKey []byte
-}
-
-const symmetricKeyEncryptedVersion = 4
-
-func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) {
- // RFC 4880, section 5.3.
- var buf [2]byte
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
- if buf[0] != symmetricKeyEncryptedVersion {
- return errors.UnsupportedError("SymmetricKeyEncrypted version")
- }
- ske.CipherFunc = CipherFunction(buf[1])
-
- if ske.CipherFunc.KeySize() == 0 {
- return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
- }
-
- ske.s2k, err = s2k.Parse(r)
- if err != nil {
- return
- }
-
- encryptedKey := make([]byte, maxSessionKeySizeInBytes)
- // The session key may follow. We just have to try and read to find
- // out. If it exists then we limit it to maxSessionKeySizeInBytes.
- n, err := readFull(r, encryptedKey)
- if err != nil && err != io.ErrUnexpectedEOF {
- return
- }
- err = nil
- if n != 0 {
- if n == maxSessionKeySizeInBytes {
- return errors.UnsupportedError("oversized encrypted session key")
- }
- ske.encryptedKey = encryptedKey[:n]
- }
-
- ske.Encrypted = true
-
- return
-}
-
-// Decrypt attempts to decrypt an encrypted session key. If it returns nil,
-// ske.Key will contain the session key.
-func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
- if !ske.Encrypted {
- return nil
- }
-
- key := make([]byte, ske.CipherFunc.KeySize())
- ske.s2k(key, passphrase)
-
- if len(ske.encryptedKey) == 0 {
- ske.Key = key
- } else {
- // the IV is all zeros
- iv := make([]byte, ske.CipherFunc.blockSize())
- c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
- c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
- ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
- if ske.CipherFunc.blockSize() == 0 {
- return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
- }
- ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
- ske.Key = ske.encryptedKey[1:]
- if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
- ske.Key = nil
- return errors.StructuralError("length of decrypted key not a multiple of block size")
- }
- }
-
- ske.Encrypted = false
- return nil
-}
-
-// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
-// packet contains a random session key, encrypted by a key derived from the
-// given passphrase. The session key is returned and must be passed to
-// SerializeSymmetricallyEncrypted.
-func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err error) {
- keySize := cipherFunc.KeySize()
- if keySize == 0 {
- return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
- }
-
- s2kBuf := new(bytes.Buffer)
- keyEncryptingKey := make([]byte, keySize)
- // s2k.Serialize salts and stretches the passphrase, and writes the
- // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
- err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase)
- if err != nil {
- return
- }
- s2kBytes := s2kBuf.Bytes()
-
- packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
- err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
- if err != nil {
- return
- }
-
- var buf [2]byte
- buf[0] = symmetricKeyEncryptedVersion
- buf[1] = byte(cipherFunc)
- _, err = w.Write(buf[:])
- if err != nil {
- return
- }
- _, err = w.Write(s2kBytes)
- if err != nil {
- return
- }
-
- sessionKey := make([]byte, keySize)
- _, err = io.ReadFull(rand, sessionKey)
- if err != nil {
- return
- }
- iv := make([]byte, cipherFunc.blockSize())
- c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
- encryptedCipherAndKey := make([]byte, keySize+1)
- c.XORKeyStream(encryptedCipherAndKey, buf[1:])
- c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
- _, err = w.Write(encryptedCipherAndKey)
- if err != nil {
- return
- }
-
- key = sessionKey
- return
-}
diff --git a/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go
deleted file mode 100644
index 87690f0b7bf..00000000000
--- a/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto/rand"
- "encoding/hex"
- "io"
- "io/ioutil"
- "testing"
-)
-
-func TestSymmetricKeyEncrypted(t *testing.T) {
- buf := readerFromHex(symmetricallyEncryptedHex)
- packet, err := Read(buf)
- if err != nil {
- t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
- return
- }
- ske, ok := packet.(*SymmetricKeyEncrypted)
- if !ok {
- t.Error("didn't find SymmetricKeyEncrypted packet")
- return
- }
- err = ske.Decrypt([]byte("password"))
- if err != nil {
- t.Error(err)
- return
- }
-
- packet, err = Read(buf)
- if err != nil {
- t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
- return
- }
- se, ok := packet.(*SymmetricallyEncrypted)
- if !ok {
- t.Error("didn't find SymmetricallyEncrypted packet")
- return
- }
- r, err := se.Decrypt(ske.CipherFunc, ske.Key)
- if err != nil {
- t.Error(err)
- return
- }
-
- contents, err := ioutil.ReadAll(r)
- if err != nil && err != io.EOF {
- t.Error(err)
- return
- }
-
- expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
- if !bytes.Equal(expectedContents, contents) {
- t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
- }
-}
-
-const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
-const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
-
-func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
- buf := bytes.NewBuffer(nil)
- passphrase := []byte("testing")
- cipherFunc := CipherAES128
-
- key, err := SerializeSymmetricKeyEncrypted(buf, rand.Reader, passphrase, cipherFunc)
- if err != nil {
- t.Errorf("failed to serialize: %s", err)
- return
- }
-
- p, err := Read(buf)
- if err != nil {
- t.Errorf("failed to reparse: %s", err)
- return
- }
- ske, ok := p.(*SymmetricKeyEncrypted)
- if !ok {
- t.Errorf("parsed a different packet type: %#v", p)
- return
- }
-
- if !ske.Encrypted {
- t.Errorf("SKE not encrypted but should be")
- }
- if ske.CipherFunc != cipherFunc {
- t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, cipherFunc)
- }
- err = ske.Decrypt(passphrase)
- if err != nil {
- t.Errorf("failed to decrypt reparsed SKE: %s", err)
- return
- }
- if !bytes.Equal(key, ske.Key) {
- t.Errorf("keys don't match after Decrpyt: %x (original) vs %x (parsed)", key, ske.Key)
- }
-}
diff --git a/libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go b/libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go
deleted file mode 100644
index e99a23b9fb2..00000000000
--- a/libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "crypto/cipher"
- "crypto/openpgp/errors"
- "crypto/sha1"
- "crypto/subtle"
- "hash"
- "io"
- "strconv"
-)
-
-// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
-// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
-// sections 5.7 and 5.13.
-type SymmetricallyEncrypted struct {
- MDC bool // true iff this is a type 18 packet and thus has an embedded MAC.
- contents io.Reader
- prefix []byte
-}
-
-const symmetricallyEncryptedVersion = 1
-
-func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
- if se.MDC {
- // See RFC 4880, section 5.13.
- var buf [1]byte
- _, err := readFull(r, buf[:])
- if err != nil {
- return err
- }
- if buf[0] != symmetricallyEncryptedVersion {
- return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
- }
- }
- se.contents = r
- return nil
-}
-
-// Decrypt returns a ReadCloser, from which the decrypted contents of the
-// packet can be read. An incorrect key can, with high probability, be detected
-// immediately and this will result in a KeyIncorrect error being returned.
-func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
- keySize := c.KeySize()
- if keySize == 0 {
- return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
- }
- if len(key) != keySize {
- return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
- }
-
- if se.prefix == nil {
- se.prefix = make([]byte, c.blockSize()+2)
- _, err := readFull(se.contents, se.prefix)
- if err != nil {
- return nil, err
- }
- } else if len(se.prefix) != c.blockSize()+2 {
- return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
- }
-
- ocfbResync := cipher.OCFBResync
- if se.MDC {
- // MDC packets use a different form of OCFB mode.
- ocfbResync = cipher.OCFBNoResync
- }
-
- s := cipher.NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
- if s == nil {
- return nil, errors.KeyIncorrectError
- }
-
- plaintext := cipher.StreamReader{S: s, R: se.contents}
-
- if se.MDC {
- // MDC packets have an embedded hash that we need to check.
- h := sha1.New()
- h.Write(se.prefix)
- return &seMDCReader{in: plaintext, h: h}, nil
- }
-
- // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
- return seReader{plaintext}, nil
-}
-
-// seReader wraps an io.Reader with a no-op Close method.
-type seReader struct {
- in io.Reader
-}
-
-func (ser seReader) Read(buf []byte) (int, error) {
- return ser.in.Read(buf)
-}
-
-func (ser seReader) Close() error {
- return nil
-}
-
-const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
-
-// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
-// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
-// MDC packet containing a hash of the previous contents which is checked
-// against the running hash. See RFC 4880, section 5.13.
-type seMDCReader struct {
- in io.Reader
- h hash.Hash
- trailer [mdcTrailerSize]byte
- scratch [mdcTrailerSize]byte
- trailerUsed int
- error bool
- eof bool
-}
-
-func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
- if ser.error {
- err = io.ErrUnexpectedEOF
- return
- }
- if ser.eof {
- err = io.EOF
- return
- }
-
- // If we haven't yet filled the trailer buffer then we must do that
- // first.
- for ser.trailerUsed < mdcTrailerSize {
- n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
- ser.trailerUsed += n
- if err == io.EOF {
- if ser.trailerUsed != mdcTrailerSize {
- n = 0
- err = io.ErrUnexpectedEOF
- ser.error = true
- return
- }
- ser.eof = true
- n = 0
- return
- }
-
- if err != nil {
- n = 0
- return
- }
- }
-
- // If it's a short read then we read into a temporary buffer and shift
- // the data into the caller's buffer.
- if len(buf) <= mdcTrailerSize {
- n, err = readFull(ser.in, ser.scratch[:len(buf)])
- copy(buf, ser.trailer[:n])
- ser.h.Write(buf[:n])
- copy(ser.trailer[:], ser.trailer[n:])
- copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
- if n < len(buf) {
- ser.eof = true
- err = io.EOF
- }
- return
- }
-
- n, err = ser.in.Read(buf[mdcTrailerSize:])
- copy(buf, ser.trailer[:])
- ser.h.Write(buf[:n])
- copy(ser.trailer[:], buf[n:])
-
- if err == io.EOF {
- ser.eof = true
- }
- return
-}
-
-// This is a new-format packet tag byte for a type 19 (MDC) packet.
-const mdcPacketTagByte = byte(0x80) | 0x40 | 19
-
-func (ser *seMDCReader) Close() error {
- if ser.error {
- return errors.SignatureError("error during reading")
- }
-
- for !ser.eof {
- // We haven't seen EOF so we need to read to the end
- var buf [1024]byte
- _, err := ser.Read(buf[:])
- if err == io.EOF {
- break
- }
- if err != nil {
- return errors.SignatureError("error during reading")
- }
- }
-
- if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
- return errors.SignatureError("MDC packet not found")
- }
- ser.h.Write(ser.trailer[:2])
-
- final := ser.h.Sum(nil)
- if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
- return errors.SignatureError("hash mismatch")
- }
- return nil
-}
-
-// An seMDCWriter writes through to an io.WriteCloser while maintains a running
-// hash of the data written. On close, it emits an MDC packet containing the
-// running hash.
-type seMDCWriter struct {
- w io.WriteCloser
- h hash.Hash
-}
-
-func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
- w.h.Write(buf)
- return w.w.Write(buf)
-}
-
-func (w *seMDCWriter) Close() (err error) {
- var buf [mdcTrailerSize]byte
-
- buf[0] = mdcPacketTagByte
- buf[1] = sha1.Size
- w.h.Write(buf[:2])
- digest := w.h.Sum(nil)
- copy(buf[2:], digest)
-
- _, err = w.w.Write(buf[:])
- if err != nil {
- return
- }
- return w.w.Close()
-}
-
-// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
-type noOpCloser struct {
- w io.Writer
-}
-
-func (c noOpCloser) Write(data []byte) (n int, err error) {
- return c.w.Write(data)
-}
-
-func (c noOpCloser) Close() error {
- return nil
-}
-
-// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
-// to w and returns a WriteCloser to which the to-be-encrypted packets can be
-// written.
-func SerializeSymmetricallyEncrypted(w io.Writer, rand io.Reader, c CipherFunction, key []byte) (contents io.WriteCloser, err error) {
- if c.KeySize() != len(key) {
- return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
- }
- writeCloser := noOpCloser{w}
- ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
- if err != nil {
- return
- }
-
- _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
- if err != nil {
- return
- }
-
- block := c.new(key)
- blockSize := block.BlockSize()
- iv := make([]byte, blockSize)
- _, err = rand.Read(iv)
- if err != nil {
- return
- }
- s, prefix := cipher.NewOCFBEncrypter(block, iv, cipher.OCFBNoResync)
- _, err = ciphertext.Write(prefix)
- if err != nil {
- return
- }
- plaintext := cipher.StreamWriter{S: s, W: ciphertext}
-
- h := sha1.New()
- h.Write(iv)
- h.Write(iv[blockSize-2:])
- contents = &seMDCWriter{w: plaintext, h: h}
- return
-}
diff --git a/libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go b/libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go
deleted file mode 100644
index f7d133d0bbe..00000000000
--- a/libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "bytes"
- "crypto/openpgp/errors"
- "crypto/rand"
- "crypto/sha1"
- "encoding/hex"
- "io"
- "io/ioutil"
- "testing"
-)
-
-// TestReader wraps a []byte and returns reads of a specific length.
-type testReader struct {
- data []byte
- stride int
-}
-
-func (t *testReader) Read(buf []byte) (n int, err error) {
- n = t.stride
- if n > len(t.data) {
- n = len(t.data)
- }
- if n > len(buf) {
- n = len(buf)
- }
- copy(buf, t.data)
- t.data = t.data[n:]
- if len(t.data) == 0 {
- err = io.EOF
- }
- return
-}
-
-func testMDCReader(t *testing.T) {
- mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)
-
- for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
- r := &testReader{data: mdcPlaintext, stride: stride}
- mdcReader := &seMDCReader{in: r, h: sha1.New()}
- body, err := ioutil.ReadAll(mdcReader)
- if err != nil {
- t.Errorf("stride: %d, error: %s", stride, err)
- continue
- }
- if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
- t.Errorf("stride: %d: bad contents %x", stride, body)
- continue
- }
-
- err = mdcReader.Close()
- if err != nil {
- t.Errorf("stride: %d, error on Close: %s", stride, err)
- }
- }
-
- mdcPlaintext[15] ^= 80
-
- r := &testReader{data: mdcPlaintext, stride: 2}
- mdcReader := &seMDCReader{in: r, h: sha1.New()}
- _, err := ioutil.ReadAll(mdcReader)
- if err != nil {
- t.Errorf("corruption test, error: %s", err)
- return
- }
- err = mdcReader.Close()
- if err == nil {
- t.Error("corruption: no error")
- } else if _, ok := err.(*errors.SignatureError); !ok {
- t.Errorf("corruption: expected SignatureError, got: %s", err)
- }
-}
-
-const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"
-
-func TestSerialize(t *testing.T) {
- buf := bytes.NewBuffer(nil)
- c := CipherAES128
- key := make([]byte, c.KeySize())
-
- w, err := SerializeSymmetricallyEncrypted(buf, rand.Reader, c, key)
- if err != nil {
- t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
- return
- }
-
- contents := []byte("hello world\n")
-
- w.Write(contents)
- w.Close()
-
- p, err := Read(buf)
- if err != nil {
- t.Errorf("error from Read: %s", err)
- return
- }
-
- se, ok := p.(*SymmetricallyEncrypted)
- if !ok {
- t.Errorf("didn't read a *SymmetricallyEncrypted")
- return
- }
-
- r, err := se.Decrypt(c, key)
- if err != nil {
- t.Errorf("error from Decrypt: %s", err)
- return
- }
-
- contentsCopy := bytes.NewBuffer(nil)
- _, err = io.Copy(contentsCopy, r)
- if err != nil {
- t.Errorf("error from io.Copy: %s", err)
- return
- }
- if !bytes.Equal(contentsCopy.Bytes(), contents) {
- t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
- }
-}
diff --git a/libgo/go/crypto/openpgp/packet/userid.go b/libgo/go/crypto/openpgp/packet/userid.go
deleted file mode 100644
index d6bea7d4acc..00000000000
--- a/libgo/go/crypto/openpgp/packet/userid.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "io"
- "io/ioutil"
- "strings"
-)
-
-// UserId contains text that is intended to represent the name and email
-// address of the key holder. See RFC 4880, section 5.11. By convention, this
-// takes the form "Full Name (Comment) <email@example.com>"
-type UserId struct {
- Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
-
- Name, Comment, Email string
-}
-
-func hasInvalidCharacters(s string) bool {
- for _, c := range s {
- switch c {
- case '(', ')', '<', '>', 0:
- return true
- }
- }
- return false
-}
-
-// NewUserId returns a UserId or nil if any of the arguments contain invalid
-// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
-func NewUserId(name, comment, email string) *UserId {
- // RFC 4880 doesn't deal with the structure of userid strings; the
- // name, comment and email form is just a convention. However, there's
- // no convention about escaping the metacharacters and GPG just refuses
- // to create user ids where, say, the name contains a '('. We mirror
- // this behaviour.
-
- if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
- return nil
- }
-
- uid := new(UserId)
- uid.Name, uid.Comment, uid.Email = name, comment, email
- uid.Id = name
- if len(comment) > 0 {
- if len(uid.Id) > 0 {
- uid.Id += " "
- }
- uid.Id += "("
- uid.Id += comment
- uid.Id += ")"
- }
- if len(email) > 0 {
- if len(uid.Id) > 0 {
- uid.Id += " "
- }
- uid.Id += "<"
- uid.Id += email
- uid.Id += ">"
- }
- return uid
-}
-
-func (uid *UserId) parse(r io.Reader) (err error) {
- // RFC 4880, section 5.11
- b, err := ioutil.ReadAll(r)
- if err != nil {
- return
- }
- uid.Id = string(b)
- uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
- return
-}
-
-// Serialize marshals uid to w in the form of an OpenPGP packet, including
-// header.
-func (uid *UserId) Serialize(w io.Writer) error {
- err := serializeHeader(w, packetTypeUserId, len(uid.Id))
- if err != nil {
- return err
- }
- _, err = w.Write([]byte(uid.Id))
- return err
-}
-
-// parseUserId extracts the name, comment and email from a user id string that
-// is formatted as "Full Name (Comment) <email@example.com>".
-func parseUserId(id string) (name, comment, email string) {
- var n, c, e struct {
- start, end int
- }
- var state int
-
- for offset, rune := range id {
- switch state {
- case 0:
- // Entering name
- n.start = offset
- state = 1
- fallthrough
- case 1:
- // In name
- if rune == '(' {
- state = 2
- n.end = offset
- } else if rune == '<' {
- state = 5
- n.end = offset
- }
- case 2:
- // Entering comment
- c.start = offset
- state = 3
- fallthrough
- case 3:
- // In comment
- if rune == ')' {
- state = 4
- c.end = offset
- }
- case 4:
- // Between comment and email
- if rune == '<' {
- state = 5
- }
- case 5:
- // Entering email
- e.start = offset
- state = 6
- fallthrough
- case 6:
- // In email
- if rune == '>' {
- state = 7
- e.end = offset
- }
- default:
- // After email
- }
- }
- switch state {
- case 1:
- // ended in the name
- n.end = len(id)
- case 3:
- // ended in comment
- c.end = len(id)
- case 6:
- // ended in email
- e.end = len(id)
- }
-
- name = strings.TrimSpace(id[n.start:n.end])
- comment = strings.TrimSpace(id[c.start:c.end])
- email = strings.TrimSpace(id[e.start:e.end])
- return
-}
diff --git a/libgo/go/crypto/openpgp/packet/userid_test.go b/libgo/go/crypto/openpgp/packet/userid_test.go
deleted file mode 100644
index 29681938938..00000000000
--- a/libgo/go/crypto/openpgp/packet/userid_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
- "testing"
-)
-
-var userIdTests = []struct {
- id string
- name, comment, email string
-}{
- {"", "", "", ""},
- {"John Smith", "John Smith", "", ""},
- {"John Smith ()", "John Smith", "", ""},
- {"John Smith () <>", "John Smith", "", ""},
- {"(comment", "", "comment", ""},
- {"(comment)", "", "comment", ""},
- {"<email", "", "", "email"},
- {"<email> sdfk", "", "", "email"},
- {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
- {" John Smith < email > lksdfj", "John Smith", "", "email"},
- {"(<foo", "", "<foo", ""},
- {"René Descartes (العربي)", "René Descartes", "العربي", ""},
-}
-
-func TestParseUserId(t *testing.T) {
- for i, test := range userIdTests {
- name, comment, email := parseUserId(test.id)
- if name != test.name {
- t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
- }
- if comment != test.comment {
- t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
- }
- if email != test.email {
- t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
- }
- }
-}
-
-var newUserIdTests = []struct {
- name, comment, email, id string
-}{
- {"foo", "", "", "foo"},
- {"", "bar", "", "(bar)"},
- {"", "", "baz", "<baz>"},
- {"foo", "bar", "", "foo (bar)"},
- {"foo", "", "baz", "foo <baz>"},
- {"", "bar", "baz", "(bar) <baz>"},
- {"foo", "bar", "baz", "foo (bar) <baz>"},
-}
-
-func TestNewUserId(t *testing.T) {
- for i, test := range newUserIdTests {
- uid := NewUserId(test.name, test.comment, test.email)
- if uid == nil {
- t.Errorf("#%d: returned nil", i)
- continue
- }
- if uid.Id != test.id {
- t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id)
- }
- }
-}
-
-var invalidNewUserIdTests = []struct {
- name, comment, email string
-}{
- {"foo(", "", ""},
- {"foo<", "", ""},
- {"", "bar)", ""},
- {"", "bar<", ""},
- {"", "", "baz>"},
- {"", "", "baz)"},
- {"", "", "baz\x00"},
-}
-
-func TestNewUserIdWithInvalidInput(t *testing.T) {
- for i, test := range invalidNewUserIdTests {
- if uid := NewUserId(test.name, test.comment, test.email); uid != nil {
- t.Errorf("#%d: returned non-nil value: %#v", i, uid)
- }
- }
-}
diff --git a/libgo/go/crypto/openpgp/read.go b/libgo/go/crypto/openpgp/read.go
deleted file mode 100644
index 1d234347041..00000000000
--- a/libgo/go/crypto/openpgp/read.go
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package openpgp implements high level operations on OpenPGP messages.
-package openpgp
-
-import (
- "crypto"
- "crypto/openpgp/armor"
- "crypto/openpgp/errors"
- "crypto/openpgp/packet"
- _ "crypto/sha256"
- "hash"
- "io"
- "strconv"
-)
-
-// SignatureType is the armor type for a PGP signature.
-var SignatureType = "PGP SIGNATURE"
-
-// readArmored reads an armored block with the given type.
-func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
- block, err := armor.Decode(r)
- if err != nil {
- return
- }
-
- if block.Type != expectedType {
- return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
- }
-
- return block.Body, nil
-}
-
-// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
-// signed message.
-type MessageDetails struct {
- IsEncrypted bool // true if the message was encrypted.
- EncryptedToKeyIds []uint64 // the list of recipient key ids.
- IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
- DecryptedWith Key // the private key used to decrypt the message, if any.
- IsSigned bool // true if the message is signed.
- SignedByKeyId uint64 // the key id of the signer, if any.
- SignedBy *Key // the key of the signer, if available.
- LiteralData *packet.LiteralData // the metadata of the contents
- UnverifiedBody io.Reader // the contents of the message.
-
- // If IsSigned is true and SignedBy is non-zero then the signature will
- // be verified as UnverifiedBody is read. The signature cannot be
- // checked until the whole of UnverifiedBody is read so UnverifiedBody
- // must be consumed until EOF before the data can trusted. Even if a
- // message isn't signed (or the signer is unknown) the data may contain
- // an authentication code that is only checked once UnverifiedBody has
- // been consumed. Once EOF has been seen, the following fields are
- // valid. (An authentication code failure is reported as a
- // SignatureError error when reading from UnverifiedBody.)
- SignatureError error // nil if the signature is good.
- Signature *packet.Signature // the signature packet itself.
-
- decrypted io.ReadCloser
-}
-
-// A PromptFunction is used as a callback by functions that may need to decrypt
-// a private key, or prompt for a passphrase. It is called with a list of
-// acceptable, encrypted private keys and a boolean that indicates whether a
-// passphrase is usable. It should either decrypt a private key or return a
-// passphrase to try. If the decrypted private key or given passphrase isn't
-// correct, the function will be called again, forever. Any error returned will
-// be passed up.
-type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
-
-// A keyEnvelopePair is used to store a private key with the envelope that
-// contains a symmetric key, encrypted with that key.
-type keyEnvelopePair struct {
- key Key
- encryptedKey *packet.EncryptedKey
-}
-
-// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
-// The given KeyRing should contain both public keys (for signature
-// verification) and, possibly encrypted, private keys for decrypting.
-func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction) (md *MessageDetails, err error) {
- var p packet.Packet
-
- var symKeys []*packet.SymmetricKeyEncrypted
- var pubKeys []keyEnvelopePair
- var se *packet.SymmetricallyEncrypted
-
- packets := packet.NewReader(r)
- md = new(MessageDetails)
- md.IsEncrypted = true
-
- // The message, if encrypted, starts with a number of packets
- // containing an encrypted decryption key. The decryption key is either
- // encrypted to a public key, or with a passphrase. This loop
- // collects these packets.
-ParsePackets:
- for {
- p, err = packets.Next()
- if err != nil {
- return nil, err
- }
- switch p := p.(type) {
- case *packet.SymmetricKeyEncrypted:
- // This packet contains the decryption key encrypted with a passphrase.
- md.IsSymmetricallyEncrypted = true
- symKeys = append(symKeys, p)
- case *packet.EncryptedKey:
- // This packet contains the decryption key encrypted to a public key.
- md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
- switch p.Algo {
- case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
- break
- default:
- continue
- }
- var keys []Key
- if p.KeyId == 0 {
- keys = keyring.DecryptionKeys()
- } else {
- keys = keyring.KeysById(p.KeyId)
- }
- for _, k := range keys {
- pubKeys = append(pubKeys, keyEnvelopePair{k, p})
- }
- case *packet.SymmetricallyEncrypted:
- se = p
- break ParsePackets
- case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
- // This message isn't encrypted.
- if len(symKeys) != 0 || len(pubKeys) != 0 {
- return nil, errors.StructuralError("key material not followed by encrypted message")
- }
- packets.Unread(p)
- return readSignedMessage(packets, nil, keyring)
- }
- }
-
- var candidates []Key
- var decrypted io.ReadCloser
-
- // Now that we have the list of encrypted keys we need to decrypt at
- // least one of them or, if we cannot, we need to call the prompt
- // function so that it can decrypt a key or give us a passphrase.
-FindKey:
- for {
- // See if any of the keys already have a private key available
- candidates = candidates[:0]
- candidateFingerprints := make(map[string]bool)
-
- for _, pk := range pubKeys {
- if pk.key.PrivateKey == nil {
- continue
- }
- if !pk.key.PrivateKey.Encrypted {
- if len(pk.encryptedKey.Key) == 0 {
- pk.encryptedKey.Decrypt(pk.key.PrivateKey)
- }
- if len(pk.encryptedKey.Key) == 0 {
- continue
- }
- decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
- if err != nil && err != errors.KeyIncorrectError {
- return nil, err
- }
- if decrypted != nil {
- md.DecryptedWith = pk.key
- break FindKey
- }
- } else {
- fpr := string(pk.key.PublicKey.Fingerprint[:])
- if v := candidateFingerprints[fpr]; v {
- continue
- }
- candidates = append(candidates, pk.key)
- candidateFingerprints[fpr] = true
- }
- }
-
- if len(candidates) == 0 && len(symKeys) == 0 {
- return nil, errors.KeyIncorrectError
- }
-
- if prompt == nil {
- return nil, errors.KeyIncorrectError
- }
-
- passphrase, err := prompt(candidates, len(symKeys) != 0)
- if err != nil {
- return nil, err
- }
-
- // Try the symmetric passphrase first
- if len(symKeys) != 0 && passphrase != nil {
- for _, s := range symKeys {
- err = s.Decrypt(passphrase)
- if err == nil && !s.Encrypted {
- decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
- if err != nil && err != errors.KeyIncorrectError {
- return nil, err
- }
- if decrypted != nil {
- break FindKey
- }
- }
-
- }
- }
- }
-
- md.decrypted = decrypted
- packets.Push(decrypted)
- return readSignedMessage(packets, md, keyring)
-}
-
-// readSignedMessage reads a possibly signed message if mdin is non-zero then
-// that structure is updated and returned. Otherwise a fresh MessageDetails is
-// used.
-func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
- if mdin == nil {
- mdin = new(MessageDetails)
- }
- md = mdin
-
- var p packet.Packet
- var h hash.Hash
- var wrappedHash hash.Hash
-FindLiteralData:
- for {
- p, err = packets.Next()
- if err != nil {
- return nil, err
- }
- switch p := p.(type) {
- case *packet.Compressed:
- packets.Push(p.Body)
- case *packet.OnePassSignature:
- if !p.IsLast {
- return nil, errors.UnsupportedError("nested signatures")
- }
-
- h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
- if err != nil {
- md = nil
- return
- }
-
- md.IsSigned = true
- md.SignedByKeyId = p.KeyId
- keys := keyring.KeysById(p.KeyId)
- for i, key := range keys {
- if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
- continue
- }
- md.SignedBy = &keys[i]
- break
- }
- case *packet.LiteralData:
- md.LiteralData = p
- break FindLiteralData
- }
- }
-
- if md.SignedBy != nil {
- md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
- } else if md.decrypted != nil {
- md.UnverifiedBody = checkReader{md}
- } else {
- md.UnverifiedBody = md.LiteralData.Body
- }
-
- return md, nil
-}
-
-// hashForSignature returns a pair of hashes that can be used to verify a
-// signature. The signature may specify that the contents of the signed message
-// should be preprocessed (i.e. to normalize line endings). Thus this function
-// returns two hashes. The second should be used to hash the message itself and
-// performs any needed preprocessing.
-func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
- h := hashId.New()
- if h == nil {
- return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
- }
-
- switch sigType {
- case packet.SigTypeBinary:
- return h, h, nil
- case packet.SigTypeText:
- return h, NewCanonicalTextHash(h), nil
- }
-
- return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
-}
-
-// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
-// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
-// MDC checks.
-type checkReader struct {
- md *MessageDetails
-}
-
-func (cr checkReader) Read(buf []byte) (n int, err error) {
- n, err = cr.md.LiteralData.Body.Read(buf)
- if err == io.EOF {
- mdcErr := cr.md.decrypted.Close()
- if mdcErr != nil {
- err = mdcErr
- }
- }
- return
-}
-
-// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
-// the data as it is read. When it sees an EOF from the underlying io.Reader
-// it parses and checks a trailing Signature packet and triggers any MDC checks.
-type signatureCheckReader struct {
- packets *packet.Reader
- h, wrappedHash hash.Hash
- md *MessageDetails
-}
-
-func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
- n, err = scr.md.LiteralData.Body.Read(buf)
- scr.wrappedHash.Write(buf[:n])
- if err == io.EOF {
- var p packet.Packet
- p, scr.md.SignatureError = scr.packets.Next()
- if scr.md.SignatureError != nil {
- return
- }
-
- var ok bool
- if scr.md.Signature, ok = p.(*packet.Signature); !ok {
- scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
- return
- }
-
- scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
-
- // The SymmetricallyEncrypted packet, if any, might have an
- // unsigned hash of its own. In order to check this we need to
- // close that Reader.
- if scr.md.decrypted != nil {
- mdcErr := scr.md.decrypted.Close()
- if mdcErr != nil {
- err = mdcErr
- }
- }
- }
- return
-}
-
-// CheckDetachedSignature takes a signed file and a detached signature and
-// returns the signer if the signature is valid. If the signer isn't know,
-// UnknownIssuerError is returned.
-func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
- p, err := packet.Read(signature)
- if err != nil {
- return
- }
-
- sig, ok := p.(*packet.Signature)
- if !ok {
- return nil, errors.StructuralError("non signature packet found")
- }
-
- if sig.IssuerKeyId == nil {
- return nil, errors.StructuralError("signature doesn't have an issuer")
- }
-
- keys := keyring.KeysById(*sig.IssuerKeyId)
- if len(keys) == 0 {
- return nil, errors.UnknownIssuerError
- }
-
- h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
- if err != nil {
- return
- }
-
- _, err = io.Copy(wrappedHash, signed)
- if err != nil && err != io.EOF {
- return
- }
-
- for _, key := range keys {
- if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
- continue
- }
- err = key.PublicKey.VerifySignature(h, sig)
- if err == nil {
- return key.Entity, nil
- }
- }
-
- if err != nil {
- return
- }
-
- return nil, errors.UnknownIssuerError
-}
-
-// CheckArmoredDetachedSignature performs the same actions as
-// CheckDetachedSignature but expects the signature to be armored.
-func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
- body, err := readArmored(signature, SignatureType)
- if err != nil {
- return
- }
-
- return CheckDetachedSignature(keyring, signed, body)
-}
diff --git a/libgo/go/crypto/openpgp/read_test.go b/libgo/go/crypto/openpgp/read_test.go
deleted file mode 100644
index d1ecad38179..00000000000
--- a/libgo/go/crypto/openpgp/read_test.go
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import (
- "bytes"
- "crypto/openpgp/errors"
- _ "crypto/sha512"
- "encoding/hex"
- "io"
- "io/ioutil"
- "testing"
-)
-
-func readerFromHex(s string) io.Reader {
- data, err := hex.DecodeString(s)
- if err != nil {
- panic("readerFromHex: bad input")
- }
- return bytes.NewBuffer(data)
-}
-
-func TestReadKeyRing(t *testing.T) {
- kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
- if err != nil {
- t.Error(err)
- return
- }
- if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B {
- t.Errorf("bad keyring: %#v", kring)
- }
-}
-
-func TestRereadKeyRing(t *testing.T) {
- kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
- if err != nil {
- t.Errorf("error in initial parse: %s", err)
- return
- }
- out := new(bytes.Buffer)
- err = kring[0].Serialize(out)
- if err != nil {
- t.Errorf("error in serialization: %s", err)
- return
- }
- kring, err = ReadKeyRing(out)
- if err != nil {
- t.Errorf("error in second parse: %s", err)
- return
- }
-
- if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB {
- t.Errorf("bad keyring: %#v", kring)
- }
-}
-
-func TestReadPrivateKeyRing(t *testing.T) {
- kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
- if err != nil {
- t.Error(err)
- return
- }
- if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil {
- t.Errorf("bad keyring: %#v", kring)
- }
-}
-
-func TestReadDSAKey(t *testing.T) {
- kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex))
- if err != nil {
- t.Error(err)
- return
- }
- if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 {
- t.Errorf("bad parse: %#v", kring)
- }
-}
-
-func TestDSAHashTruncatation(t *testing.T) {
- // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo
- // SHA512 in order to require DSA hash truncation to verify correctly.
- _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512))
- if err != nil {
- t.Error(err)
- }
-}
-
-func TestGetKeyById(t *testing.T) {
- kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-
- keys := kring.KeysById(0xa34d7e18c20c31bb)
- if len(keys) != 1 || keys[0].Entity != kring[0] {
- t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
- }
-
- keys = kring.KeysById(0xfd94408d4543314f)
- if len(keys) != 1 || keys[0].Entity != kring[0] {
- t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
- }
-}
-
-func checkSignedMessage(t *testing.T, signedHex, expected string) {
- kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-
- md, err := ReadMessage(readerFromHex(signedHex), kring, nil)
- if err != nil {
- t.Error(err)
- return
- }
-
- if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted {
- t.Errorf("bad MessageDetails: %#v", md)
- }
-
- contents, err := ioutil.ReadAll(md.UnverifiedBody)
- if err != nil {
- t.Errorf("error reading UnverifiedBody: %s", err)
- }
- if string(contents) != expected {
- t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
- }
- if md.SignatureError != nil || md.Signature == nil {
- t.Errorf("failed to validate: %s", md.SignatureError)
- }
-}
-
-func TestSignedMessage(t *testing.T) {
- checkSignedMessage(t, signedMessageHex, signedInput)
-}
-
-func TestTextSignedMessage(t *testing.T) {
- checkSignedMessage(t, signedTextMessageHex, signedTextInput)
-}
-
-var signedEncryptedMessageTests = []struct {
- keyRingHex string
- messageHex string
- signedByKeyId uint64
- encryptedToKeyId uint64
-}{
- {
- testKeys1And2PrivateHex,
- signedEncryptedMessageHex,
- 0xa34d7e18c20c31bb,
- 0x2a67d68660df41c7,
- },
- {
- dsaElGamalTestKeysHex,
- signedEncryptedMessage2Hex,
- 0x33af447ccd759b09,
- 0xcf6a7abcd43e3673,
- },
-}
-
-func TestSignedEncryptedMessage(t *testing.T) {
- for i, test := range signedEncryptedMessageTests {
- expected := "Signed and encrypted message\n"
- kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
- prompt := func(keys []Key, symmetric bool) ([]byte, error) {
- if symmetric {
- t.Errorf("prompt: message was marked as symmetrically encrypted")
- return nil, errors.KeyIncorrectError
- }
-
- if len(keys) == 0 {
- t.Error("prompt: no keys requested")
- return nil, errors.KeyIncorrectError
- }
-
- err := keys[0].PrivateKey.Decrypt([]byte("passphrase"))
- if err != nil {
- t.Errorf("prompt: error decrypting key: %s", err)
- return nil, errors.KeyIncorrectError
- }
-
- return nil, nil
- }
-
- md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt)
- if err != nil {
- t.Errorf("#%d: error reading message: %s", i, err)
- return
- }
-
- if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId {
- t.Errorf("#%d: bad MessageDetails: %#v", i, md)
- }
-
- contents, err := ioutil.ReadAll(md.UnverifiedBody)
- if err != nil {
- t.Errorf("#%d: error reading UnverifiedBody: %s", i, err)
- }
- if string(contents) != expected {
- t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected)
- }
-
- if md.SignatureError != nil || md.Signature == nil {
- t.Errorf("#%d: failed to validate: %s", i, md.SignatureError)
- }
- }
-}
-
-func TestUnspecifiedRecipient(t *testing.T) {
- expected := "Recipient unspecified\n"
- kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-
- md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil)
- if err != nil {
- t.Errorf("error reading message: %s", err)
- return
- }
-
- contents, err := ioutil.ReadAll(md.UnverifiedBody)
- if err != nil {
- t.Errorf("error reading UnverifiedBody: %s", err)
- }
- if string(contents) != expected {
- t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
- }
-}
-
-func TestSymmetricallyEncrypted(t *testing.T) {
- expected := "Symmetrically encrypted.\n"
-
- prompt := func(keys []Key, symmetric bool) ([]byte, error) {
- if len(keys) != 0 {
- t.Errorf("prompt: len(keys) = %d (want 0)", len(keys))
- }
-
- if !symmetric {
- t.Errorf("symmetric is not set")
- }
-
- return []byte("password"), nil
- }
-
- md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt)
- if err != nil {
- t.Errorf("ReadMessage: %s", err)
- return
- }
-
- contents, err := ioutil.ReadAll(md.UnverifiedBody)
- if err != nil {
- t.Errorf("ReadAll: %s", err)
- }
-
- expectedCreationTime := uint32(1295992998)
- if md.LiteralData.Time != expectedCreationTime {
- t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime)
- }
-
- if string(contents) != expected {
- t.Errorf("contents got: %s want: %s", string(contents), expected)
- }
-}
-
-func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) {
- signed := bytes.NewBufferString(sigInput)
- signer, err := CheckDetachedSignature(kring, signed, signature)
- if err != nil {
- t.Errorf("%s: signature error: %s", tag, err)
- return
- }
- if signer == nil {
- t.Errorf("%s: signer is nil", tag)
- return
- }
- if signer.PrimaryKey.KeyId != expectedSignerKeyId {
- t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId)
- }
-}
-
-func TestDetachedSignature(t *testing.T) {
- kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
- testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId)
- testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId)
-}
-
-func TestDetachedSignatureDSA(t *testing.T) {
- kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex))
- testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
-}
-
-func TestReadingArmoredPrivateKey(t *testing.T) {
- el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
- if err != nil {
- t.Error(err)
- }
- if len(el) != 1 {
- t.Errorf("got %d entities, wanted 1\n", len(el))
- }
-}
-
-func TestNoArmoredData(t *testing.T) {
- _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
- if _, ok := err.(errors.InvalidArgumentError); !ok {
- t.Errorf("error was not an InvalidArgumentError: %s", err)
- }
-}
-
-const testKey1KeyId = 0xA34D7E18C20C31BB
-const testKey3KeyId = 0x338934250CCC0360
-
-const signedInput = "Signed message\nline 2\nline 3\n"
-const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
-
-const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
-
-const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
-
-const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
-
-const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
-
-const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
-
-const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
-
-const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
-
-const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
-
-const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
-
-const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d"
-
-const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
-
-const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6"
-
-const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
-
-const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
-
-const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1.4.10 (GNU/Linux)
-
-lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
-idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
-vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
-AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
-0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
-IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
-VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
-gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
-TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
-q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
-dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
-CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
-ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
-eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
-AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
-bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
-/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
-A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
-TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
-lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
-rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
-oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
-QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
-nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
-AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
-BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
-AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
-VrM0m72/jnpKo04=
-=zNCn
------END PGP PRIVATE KEY BLOCK-----`
-
-const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
diff --git a/libgo/go/crypto/openpgp/s2k/s2k.go b/libgo/go/crypto/openpgp/s2k/s2k.go
deleted file mode 100644
index 39479a1f1c6..00000000000
--- a/libgo/go/crypto/openpgp/s2k/s2k.go
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package s2k implements the various OpenPGP string-to-key transforms as
-// specified in RFC 4800 section 3.7.1.
-package s2k
-
-import (
- "crypto"
- "crypto/openpgp/errors"
- "hash"
- "io"
- "strconv"
-)
-
-// Simple writes to out the result of computing the Simple S2K function (RFC
-// 4880, section 3.7.1.1) using the given hash and input passphrase.
-func Simple(out []byte, h hash.Hash, in []byte) {
- Salted(out, h, in, nil)
-}
-
-var zero [1]byte
-
-// Salted writes to out the result of computing the Salted S2K function (RFC
-// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
-func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
- done := 0
- var digest []byte
-
- for i := 0; done < len(out); i++ {
- h.Reset()
- for j := 0; j < i; j++ {
- h.Write(zero[:])
- }
- h.Write(salt)
- h.Write(in)
- digest = h.Sum(digest[:0])
- n := copy(out[done:], digest)
- done += n
- }
-}
-
-// Iterated writes to out the result of computing the Iterated and Salted S2K
-// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
-// salt and iteration count.
-func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
- combined := make([]byte, len(in)+len(salt))
- copy(combined, salt)
- copy(combined[len(salt):], in)
-
- if count < len(combined) {
- count = len(combined)
- }
-
- done := 0
- var digest []byte
- for i := 0; done < len(out); i++ {
- h.Reset()
- for j := 0; j < i; j++ {
- h.Write(zero[:])
- }
- written := 0
- for written < count {
- if written+len(combined) > count {
- todo := count - written
- h.Write(combined[:todo])
- written = count
- } else {
- h.Write(combined)
- written += len(combined)
- }
- }
- digest = h.Sum(digest[:0])
- n := copy(out[done:], digest)
- done += n
- }
-}
-
-// Parse reads a binary specification for a string-to-key transformation from r
-// and returns a function which performs that transform.
-func Parse(r io.Reader) (f func(out, in []byte), err error) {
- var buf [9]byte
-
- _, err = io.ReadFull(r, buf[:2])
- if err != nil {
- return
- }
-
- hash, ok := HashIdToHash(buf[1])
- if !ok {
- return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
- }
- h := hash.New()
- if h == nil {
- return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
- }
-
- switch buf[0] {
- case 1:
- f := func(out, in []byte) {
- Simple(out, h, in)
- }
- return f, nil
- case 2:
- _, err = io.ReadFull(r, buf[:8])
- if err != nil {
- return
- }
- f := func(out, in []byte) {
- Salted(out, h, in, buf[:8])
- }
- return f, nil
- case 3:
- _, err = io.ReadFull(r, buf[:9])
- if err != nil {
- return
- }
- count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6)
- f := func(out, in []byte) {
- Iterated(out, h, in, buf[:8], count)
- }
- return f, nil
- }
-
- return nil, errors.UnsupportedError("S2K function")
-}
-
-// Serialize salts and stretches the given passphrase and writes the resulting
-// key into key. It also serializes an S2K descriptor to w.
-func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte) error {
- var buf [11]byte
- buf[0] = 3 /* iterated and salted */
- buf[1], _ = HashToHashId(crypto.SHA1)
- salt := buf[2:10]
- if _, err := io.ReadFull(rand, salt); err != nil {
- return err
- }
- const count = 65536 // this is the default in gpg
- buf[10] = 96 // 65536 iterations
- if _, err := w.Write(buf[:]); err != nil {
- return err
- }
-
- Iterated(key, crypto.SHA1.New(), passphrase, salt, count)
- return nil
-}
-
-// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
-// Go's crypto.Hash type. See RFC 4880, section 9.4.
-var hashToHashIdMapping = []struct {
- id byte
- hash crypto.Hash
-}{
- {1, crypto.MD5},
- {2, crypto.SHA1},
- {3, crypto.RIPEMD160},
- {8, crypto.SHA256},
- {9, crypto.SHA384},
- {10, crypto.SHA512},
- {11, crypto.SHA224},
-}
-
-// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
-// hash id.
-func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
- for _, m := range hashToHashIdMapping {
- if m.id == id {
- return m.hash, true
- }
- }
- return 0, false
-}
-
-// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
-func HashToHashId(h crypto.Hash) (id byte, ok bool) {
- for _, m := range hashToHashIdMapping {
- if m.hash == h {
- return m.id, true
- }
- }
- return 0, false
-}
diff --git a/libgo/go/crypto/openpgp/s2k/s2k_test.go b/libgo/go/crypto/openpgp/s2k/s2k_test.go
deleted file mode 100644
index 3a094a10f1f..00000000000
--- a/libgo/go/crypto/openpgp/s2k/s2k_test.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package s2k
-
-import (
- "bytes"
- "crypto/rand"
- "crypto/sha1"
- "encoding/hex"
- "testing"
-)
-
-var saltedTests = []struct {
- in, out string
-}{
- {"hello", "10295ac1"},
- {"world", "ac587a5e"},
- {"foo", "4dda8077"},
- {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
- {"x", "f1d3f289"},
- {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
-}
-
-func TestSalted(t *testing.T) {
- h := sha1.New()
- salt := [4]byte{1, 2, 3, 4}
-
- for i, test := range saltedTests {
- expected, _ := hex.DecodeString(test.out)
- out := make([]byte, len(expected))
- Salted(out, h, []byte(test.in), salt[:])
- if !bytes.Equal(expected, out) {
- t.Errorf("#%d, got: %x want: %x", i, out, expected)
- }
- }
-}
-
-var iteratedTests = []struct {
- in, out string
-}{
- {"hello", "83126105"},
- {"world", "6fa317f9"},
- {"foo", "8fbc35b9"},
- {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
- {"x", "5a684dfe"},
- {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
-}
-
-func TestIterated(t *testing.T) {
- h := sha1.New()
- salt := [4]byte{4, 3, 2, 1}
-
- for i, test := range iteratedTests {
- expected, _ := hex.DecodeString(test.out)
- out := make([]byte, len(expected))
- Iterated(out, h, []byte(test.in), salt[:], 31)
- if !bytes.Equal(expected, out) {
- t.Errorf("#%d, got: %x want: %x", i, out, expected)
- }
- }
-}
-
-var parseTests = []struct {
- spec, in, out string
-}{
- /* Simple with SHA1 */
- {"0102", "hello", "aaf4c61d"},
- /* Salted with SHA1 */
- {"02020102030405060708", "hello", "f4f7d67e"},
- /* Iterated with SHA1 */
- {"03020102030405060708f1", "hello", "f2a57b7c"},
-}
-
-func TestParse(t *testing.T) {
- for i, test := range parseTests {
- spec, _ := hex.DecodeString(test.spec)
- buf := bytes.NewBuffer(spec)
- f, err := Parse(buf)
- if err != nil {
- t.Errorf("%d: Parse returned error: %s", i, err)
- continue
- }
-
- expected, _ := hex.DecodeString(test.out)
- out := make([]byte, len(expected))
- f(out, []byte(test.in))
- if !bytes.Equal(out, expected) {
- t.Errorf("%d: output got: %x want: %x", i, out, expected)
- }
- if testing.Short() {
- break
- }
- }
-}
-
-func TestSerialize(t *testing.T) {
- buf := bytes.NewBuffer(nil)
- key := make([]byte, 16)
- passphrase := []byte("testing")
- err := Serialize(buf, key, rand.Reader, passphrase)
- if err != nil {
- t.Errorf("failed to serialize: %s", err)
- return
- }
-
- f, err := Parse(buf)
- if err != nil {
- t.Errorf("failed to reparse: %s", err)
- return
- }
- key2 := make([]byte, len(key))
- f(key2, passphrase)
- if !bytes.Equal(key2, key) {
- t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
- }
-}
diff --git a/libgo/go/crypto/openpgp/write.go b/libgo/go/crypto/openpgp/write.go
deleted file mode 100644
index 73daa113121..00000000000
--- a/libgo/go/crypto/openpgp/write.go
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import (
- "crypto"
- "crypto/openpgp/armor"
- "crypto/openpgp/errors"
- "crypto/openpgp/packet"
- "crypto/openpgp/s2k"
- "crypto/rand"
- _ "crypto/sha256"
- "hash"
- "io"
- "strconv"
- "time"
-)
-
-// DetachSign signs message with the private key from signer (which must
-// already have been decrypted) and writes the signature to w.
-func DetachSign(w io.Writer, signer *Entity, message io.Reader) error {
- return detachSign(w, signer, message, packet.SigTypeBinary)
-}
-
-// ArmoredDetachSign signs message with the private key from signer (which
-// must already have been decrypted) and writes an armored signature to w.
-func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader) (err error) {
- return armoredDetachSign(w, signer, message, packet.SigTypeBinary)
-}
-
-// DetachSignText signs message (after canonicalising the line endings) with
-// the private key from signer (which must already have been decrypted) and
-// writes the signature to w.
-func DetachSignText(w io.Writer, signer *Entity, message io.Reader) error {
- return detachSign(w, signer, message, packet.SigTypeText)
-}
-
-// ArmoredDetachSignText signs message (after canonicalising the line endings)
-// with the private key from signer (which must already have been decrypted)
-// and writes an armored signature to w.
-func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader) error {
- return armoredDetachSign(w, signer, message, packet.SigTypeText)
-}
-
-func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err error) {
- out, err := armor.Encode(w, SignatureType, nil)
- if err != nil {
- return
- }
- err = detachSign(out, signer, message, sigType)
- if err != nil {
- return
- }
- return out.Close()
-}
-
-func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err error) {
- if signer.PrivateKey == nil {
- return errors.InvalidArgumentError("signing key doesn't have a private key")
- }
- if signer.PrivateKey.Encrypted {
- return errors.InvalidArgumentError("signing key is encrypted")
- }
-
- sig := new(packet.Signature)
- sig.SigType = sigType
- sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
- sig.Hash = crypto.SHA256
- sig.CreationTime = time.Now()
- sig.IssuerKeyId = &signer.PrivateKey.KeyId
-
- h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
- if err != nil {
- return
- }
- io.Copy(wrappedHash, message)
-
- err = sig.Sign(rand.Reader, h, signer.PrivateKey)
- if err != nil {
- return
- }
-
- return sig.Serialize(w)
-}
-
-// FileHints contains metadata about encrypted files. This metadata is, itself,
-// encrypted.
-type FileHints struct {
- // IsBinary can be set to hint that the contents are binary data.
- IsBinary bool
- // FileName hints at the name of the file that should be written. It's
- // truncated to 255 bytes if longer. It may be empty to suggest that the
- // file should not be written to disk. It may be equal to "_CONSOLE" to
- // suggest the data should not be written to disk.
- FileName string
- // ModTime contains the modification time of the file, or the zero time if not applicable.
- ModTime time.Time
-}
-
-// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
-// The resulting WriteCloser must be closed after the contents of the file have
-// been written.
-func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints) (plaintext io.WriteCloser, err error) {
- if hints == nil {
- hints = &FileHints{}
- }
-
- key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, rand.Reader, passphrase, packet.CipherAES128)
- if err != nil {
- return
- }
- w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, packet.CipherAES128, key)
- if err != nil {
- return
- }
- var epochSeconds uint32
- if !hints.ModTime.IsZero() {
- epochSeconds = uint32(hints.ModTime.Unix())
- }
- return packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
-}
-
-// intersectPreferences mutates and returns a prefix of a that contains only
-// the values in the intersection of a and b. The order of a is preserved.
-func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
- var j int
- for _, v := range a {
- for _, v2 := range b {
- if v == v2 {
- a[j] = v
- j++
- break
- }
- }
- }
-
- return a[:j]
-}
-
-func hashToHashId(h crypto.Hash) uint8 {
- v, ok := s2k.HashToHashId(h)
- if !ok {
- panic("tried to convert unknown hash")
- }
- return v
-}
-
-// Encrypt encrypts a message to a number of recipients and, optionally, signs
-// it. hints contains optional information, that is also encrypted, that aids
-// the recipients in processing the message. The resulting WriteCloser must
-// be closed after the contents of the file have been written.
-func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints) (plaintext io.WriteCloser, err error) {
- var signer *packet.PrivateKey
- if signed != nil {
- signer = signed.signingKey().PrivateKey
- if signer == nil || signer.Encrypted {
- return nil, errors.InvalidArgumentError("signing key must be decrypted")
- }
- }
-
- // These are the possible ciphers that we'll use for the message.
- candidateCiphers := []uint8{
- uint8(packet.CipherAES128),
- uint8(packet.CipherAES256),
- uint8(packet.CipherCAST5),
- }
- // These are the possible hash functions that we'll use for the signature.
- candidateHashes := []uint8{
- hashToHashId(crypto.SHA256),
- hashToHashId(crypto.SHA512),
- hashToHashId(crypto.SHA1),
- hashToHashId(crypto.RIPEMD160),
- }
- // In the event that a recipient doesn't specify any supported ciphers
- // or hash functions, these are the ones that we assume that every
- // implementation supports.
- defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
- defaultHashes := candidateHashes[len(candidateHashes)-1:]
-
- encryptKeys := make([]Key, len(to))
- for i := range to {
- encryptKeys[i] = to[i].encryptionKey()
- if encryptKeys[i].PublicKey == nil {
- return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
- }
-
- sig := to[i].primaryIdentity().SelfSignature
-
- preferredSymmetric := sig.PreferredSymmetric
- if len(preferredSymmetric) == 0 {
- preferredSymmetric = defaultCiphers
- }
- preferredHashes := sig.PreferredHash
- if len(preferredHashes) == 0 {
- preferredHashes = defaultHashes
- }
- candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
- candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
- }
-
- if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
- return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
- }
-
- cipher := packet.CipherFunction(candidateCiphers[0])
- hash, _ := s2k.HashIdToHash(candidateHashes[0])
- symKey := make([]byte, cipher.KeySize())
- if _, err := io.ReadFull(rand.Reader, symKey); err != nil {
- return nil, err
- }
-
- for _, key := range encryptKeys {
- if err := packet.SerializeEncryptedKey(ciphertext, rand.Reader, key.PublicKey, cipher, symKey); err != nil {
- return nil, err
- }
- }
-
- encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, cipher, symKey)
- if err != nil {
- return
- }
-
- if signer != nil {
- ops := &packet.OnePassSignature{
- SigType: packet.SigTypeBinary,
- Hash: hash,
- PubKeyAlgo: signer.PubKeyAlgo,
- KeyId: signer.KeyId,
- IsLast: true,
- }
- if err := ops.Serialize(encryptedData); err != nil {
- return nil, err
- }
- }
-
- if hints == nil {
- hints = &FileHints{}
- }
-
- w := encryptedData
- if signer != nil {
- // If we need to write a signature packet after the literal
- // data then we need to stop literalData from closing
- // encryptedData.
- w = noOpCloser{encryptedData}
-
- }
- var epochSeconds uint32
- if !hints.ModTime.IsZero() {
- epochSeconds = uint32(hints.ModTime.Unix())
- }
- literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
- if err != nil {
- return nil, err
- }
-
- if signer != nil {
- return signatureWriter{encryptedData, literalData, hash, hash.New(), signer}, nil
- }
- return literalData, nil
-}
-
-// signatureWriter hashes the contents of a message while passing it along to
-// literalData. When closed, it closes literalData, writes a signature packet
-// to encryptedData and then also closes encryptedData.
-type signatureWriter struct {
- encryptedData io.WriteCloser
- literalData io.WriteCloser
- hashType crypto.Hash
- h hash.Hash
- signer *packet.PrivateKey
-}
-
-func (s signatureWriter) Write(data []byte) (int, error) {
- s.h.Write(data)
- return s.literalData.Write(data)
-}
-
-func (s signatureWriter) Close() error {
- sig := &packet.Signature{
- SigType: packet.SigTypeBinary,
- PubKeyAlgo: s.signer.PubKeyAlgo,
- Hash: s.hashType,
- CreationTime: time.Now(),
- IssuerKeyId: &s.signer.KeyId,
- }
-
- if err := sig.Sign(rand.Reader, s.h, s.signer); err != nil {
- return err
- }
- if err := s.literalData.Close(); err != nil {
- return err
- }
- if err := sig.Serialize(s.encryptedData); err != nil {
- return err
- }
- return s.encryptedData.Close()
-}
-
-// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
-// TODO: we have two of these in OpenPGP packages alone. This probably needs
-// to be promoted somewhere more common.
-type noOpCloser struct {
- w io.Writer
-}
-
-func (c noOpCloser) Write(data []byte) (n int, err error) {
- return c.w.Write(data)
-}
-
-func (c noOpCloser) Close() error {
- return nil
-}
diff --git a/libgo/go/crypto/openpgp/write_test.go b/libgo/go/crypto/openpgp/write_test.go
deleted file mode 100644
index 7df02e7bd13..00000000000
--- a/libgo/go/crypto/openpgp/write_test.go
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import (
- "bytes"
- "crypto/rand"
- "io"
- "io/ioutil"
- "testing"
- "time"
-)
-
-func TestSignDetached(t *testing.T) {
- kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
- out := bytes.NewBuffer(nil)
- message := bytes.NewBufferString(signedInput)
- err := DetachSign(out, kring[0], message)
- if err != nil {
- t.Error(err)
- }
-
- testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
-}
-
-func TestSignTextDetached(t *testing.T) {
- kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
- out := bytes.NewBuffer(nil)
- message := bytes.NewBufferString(signedInput)
- err := DetachSignText(out, kring[0], message)
- if err != nil {
- t.Error(err)
- }
-
- testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
-}
-
-func TestSignDetachedDSA(t *testing.T) {
- kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex))
- out := bytes.NewBuffer(nil)
- message := bytes.NewBufferString(signedInput)
- err := DetachSign(out, kring[0], message)
- if err != nil {
- t.Error(err)
- }
-
- testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId)
-}
-
-func TestNewEntity(t *testing.T) {
- if testing.Short() {
- return
- }
-
- e, err := NewEntity(rand.Reader, time.Now(), "Test User", "test", "test@example.com")
- if err != nil {
- t.Errorf("failed to create entity: %s", err)
- return
- }
-
- w := bytes.NewBuffer(nil)
- if err := e.SerializePrivate(w); err != nil {
- t.Errorf("failed to serialize entity: %s", err)
- return
- }
- serialized := w.Bytes()
-
- el, err := ReadKeyRing(w)
- if err != nil {
- t.Errorf("failed to reparse entity: %s", err)
- return
- }
-
- if len(el) != 1 {
- t.Errorf("wrong number of entities found, got %d, want 1", len(el))
- }
-
- w = bytes.NewBuffer(nil)
- if err := e.SerializePrivate(w); err != nil {
- t.Errorf("failed to serialize entity second time: %s", err)
- return
- }
-
- if !bytes.Equal(w.Bytes(), serialized) {
- t.Errorf("results differed")
- }
-}
-
-func TestSymmetricEncryption(t *testing.T) {
- buf := new(bytes.Buffer)
- plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil)
- if err != nil {
- t.Errorf("error writing headers: %s", err)
- return
- }
- message := []byte("hello world\n")
- _, err = plaintext.Write(message)
- if err != nil {
- t.Errorf("error writing to plaintext writer: %s", err)
- }
- err = plaintext.Close()
- if err != nil {
- t.Errorf("error closing plaintext writer: %s", err)
- }
-
- md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) {
- return []byte("testing"), nil
- })
- if err != nil {
- t.Errorf("error rereading message: %s", err)
- }
- messageBuf := bytes.NewBuffer(nil)
- _, err = io.Copy(messageBuf, md.UnverifiedBody)
- if err != nil {
- t.Errorf("error rereading message: %s", err)
- }
- if !bytes.Equal(message, messageBuf.Bytes()) {
- t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message)
- }
-}
-
-var testEncryptionTests = []struct {
- keyRingHex string
- isSigned bool
-}{
- {
- testKeys1And2PrivateHex,
- false,
- },
- {
- testKeys1And2PrivateHex,
- true,
- },
- {
- dsaElGamalTestKeysHex,
- false,
- },
- {
- dsaElGamalTestKeysHex,
- true,
- },
-}
-
-func TestEncryption(t *testing.T) {
- for i, test := range testEncryptionTests {
- kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
-
- passphrase := []byte("passphrase")
- for _, entity := range kring {
- if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
- err := entity.PrivateKey.Decrypt(passphrase)
- if err != nil {
- t.Errorf("#%d: failed to decrypt key", i)
- }
- }
- for _, subkey := range entity.Subkeys {
- if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
- err := subkey.PrivateKey.Decrypt(passphrase)
- if err != nil {
- t.Errorf("#%d: failed to decrypt subkey", i)
- }
- }
- }
- }
-
- var signed *Entity
- if test.isSigned {
- signed = kring[0]
- }
-
- buf := new(bytes.Buffer)
- w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */ )
- if err != nil {
- t.Errorf("#%d: error in Encrypt: %s", i, err)
- continue
- }
-
- const message = "testing"
- _, err = w.Write([]byte(message))
- if err != nil {
- t.Errorf("#%d: error writing plaintext: %s", i, err)
- continue
- }
- err = w.Close()
- if err != nil {
- t.Errorf("#%d: error closing WriteCloser: %s", i, err)
- continue
- }
-
- md, err := ReadMessage(buf, kring, nil /* no prompt */ )
- if err != nil {
- t.Errorf("#%d: error reading message: %s", i, err)
- continue
- }
-
- if test.isSigned {
- expectedKeyId := kring[0].signingKey().PublicKey.KeyId
- if md.SignedByKeyId != expectedKeyId {
- t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, *md.SignedBy, expectedKeyId)
- }
- if md.SignedBy == nil {
- t.Errorf("#%d: failed to find the signing Entity", i)
- }
- }
-
- plaintext, err := ioutil.ReadAll(md.UnverifiedBody)
- if err != nil {
- t.Errorf("#%d: error reading encrypted contents: %s", i, err)
- continue
- }
-
- expectedKeyId := kring[0].encryptionKey().PublicKey.KeyId
- if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId {
- t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds)
- }
-
- if string(plaintext) != message {
- t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message)
- }
-
- if test.isSigned {
- if md.SignatureError != nil {
- t.Errorf("#%d: signature error: %s", i, md.SignatureError)
- }
- if md.Signature == nil {
- t.Error("signature missing")
- }
- }
- }
-}
diff --git a/libgo/go/crypto/ripemd160/ripemd160.go b/libgo/go/crypto/ripemd160/ripemd160.go
deleted file mode 100644
index da690f0b92f..00000000000
--- a/libgo/go/crypto/ripemd160/ripemd160.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ripemd160 implements the RIPEMD-160 hash algorithm.
-package ripemd160
-
-// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
-// Preneel with specifications available at:
-// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
-
-import (
- "crypto"
- "hash"
-)
-
-func init() {
- crypto.RegisterHash(crypto.RIPEMD160, New)
-}
-
-// The size of the checksum in bytes.
-const Size = 20
-
-// The block size of the hash algorithm in bytes.
-const BlockSize = 64
-
-const (
- _s0 = 0x67452301
- _s1 = 0xefcdab89
- _s2 = 0x98badcfe
- _s3 = 0x10325476
- _s4 = 0xc3d2e1f0
-)
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
- s [5]uint32 // running context
- x [BlockSize]byte // temporary buffer
- nx int // index into x
- tc uint64 // total count of bytes processed
-}
-
-func (d *digest) Reset() {
- d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4
- d.nx = 0
- d.tc = 0
-}
-
-// New returns a new hash.Hash computing the checksum.
-func New() hash.Hash {
- result := new(digest)
- result.Reset()
- return result
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return BlockSize }
-
-func (d *digest) Write(p []byte) (nn int, err error) {
- nn = len(p)
- d.tc += uint64(nn)
- if d.nx > 0 {
- n := len(p)
- if n > BlockSize-d.nx {
- n = BlockSize - d.nx
- }
- for i := 0; i < n; i++ {
- d.x[d.nx+i] = p[i]
- }
- d.nx += n
- if d.nx == BlockSize {
- _Block(d, d.x[0:])
- d.nx = 0
- }
- p = p[n:]
- }
- n := _Block(d, p)
- p = p[n:]
- if len(p) > 0 {
- d.nx = copy(d.x[:], p)
- }
- return
-}
-
-func (d0 *digest) Sum(in []byte) []byte {
- // Make a copy of d0 so that caller can keep writing and summing.
- d := *d0
-
- // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
- tc := d.tc
- var tmp [64]byte
- tmp[0] = 0x80
- if tc%64 < 56 {
- d.Write(tmp[0 : 56-tc%64])
- } else {
- d.Write(tmp[0 : 64+56-tc%64])
- }
-
- // Length in bits.
- tc <<= 3
- for i := uint(0); i < 8; i++ {
- tmp[i] = byte(tc >> (8 * i))
- }
- d.Write(tmp[0:8])
-
- if d.nx != 0 {
- panic("d.nx != 0")
- }
-
- var digest [Size]byte
- for i, s := range d.s {
- digest[i*4] = byte(s)
- digest[i*4+1] = byte(s >> 8)
- digest[i*4+2] = byte(s >> 16)
- digest[i*4+3] = byte(s >> 24)
- }
-
- return append(in, digest[:]...)
-}
diff --git a/libgo/go/crypto/ripemd160/ripemd160_test.go b/libgo/go/crypto/ripemd160/ripemd160_test.go
deleted file mode 100644
index 5df1b2593d2..00000000000
--- a/libgo/go/crypto/ripemd160/ripemd160_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ripemd160
-
-// Test vectors are from:
-// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
-
-import (
- "fmt"
- "io"
- "testing"
-)
-
-type mdTest struct {
- out string
- in string
-}
-
-var vectors = [...]mdTest{
- {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
- {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"},
- {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"},
- {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"},
- {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"},
- {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
- {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
- {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
-}
-
-func TestVectors(t *testing.T) {
- for i := 0; i < len(vectors); i++ {
- tv := vectors[i]
- md := New()
- for j := 0; j < 3; j++ {
- if j < 2 {
- io.WriteString(md, tv.in)
- } else {
- io.WriteString(md, tv.in[0:len(tv.in)/2])
- md.Sum(nil)
- io.WriteString(md, tv.in[len(tv.in)/2:])
- }
- s := fmt.Sprintf("%x", md.Sum(nil))
- if s != tv.out {
- t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out)
- }
- md.Reset()
- }
- }
-}
-
-func TestMillionA(t *testing.T) {
- md := New()
- for i := 0; i < 100000; i++ {
- io.WriteString(md, "aaaaaaaaaa")
- }
- out := "52783243c1697bdbe16d37f97f68f08325dc1528"
- s := fmt.Sprintf("%x", md.Sum(nil))
- if s != out {
- t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out)
- }
- md.Reset()
-}
diff --git a/libgo/go/crypto/ripemd160/ripemd160block.go b/libgo/go/crypto/ripemd160/ripemd160block.go
deleted file mode 100644
index 7bc8e6c485e..00000000000
--- a/libgo/go/crypto/ripemd160/ripemd160block.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// RIPEMD-160 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-package ripemd160
-
-// work buffer indices and roll amounts for one line
-var _n = [80]uint{
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
- 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
- 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
- 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
-}
-
-var _r = [80]uint{
- 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
- 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
- 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
- 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
- 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
-}
-
-// same for the other parallel one
-var n_ = [80]uint{
- 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
- 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
- 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
- 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
- 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
-}
-
-var r_ = [80]uint{
- 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
- 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
- 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
- 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
- 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
-}
-
-func _Block(md *digest, p []byte) int {
- n := 0
- var x [16]uint32
- var alpha, beta uint32
- for len(p) >= BlockSize {
- a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4]
- aa, bb, cc, dd, ee := a, b, c, d, e
- j := 0
- for i := 0; i < 16; i++ {
- x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
- j += 4
- }
-
- // round 1
- i := 0
- for i < 16 {
- alpha = a + (b ^ c ^ d) + x[_n[i]]
- s := _r[i]
- alpha = (alpha<<s | alpha>>(32-s)) + e
- beta = c<<10 | c>>22
- a, b, c, d, e = e, alpha, b, beta, d
-
- // parallel line
- alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6
- s = r_[i]
- alpha = (alpha<<s | alpha>>(32-s)) + ee
- beta = cc<<10 | cc>>22
- aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
- i++
- }
-
- // round 2
- for i < 32 {
- alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999
- s := _r[i]
- alpha = (alpha<<s | alpha>>(32-s)) + e
- beta = c<<10 | c>>22
- a, b, c, d, e = e, alpha, b, beta, d
-
- // parallel line
- alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124
- s = r_[i]
- alpha = (alpha<<s | alpha>>(32-s)) + ee
- beta = cc<<10 | cc>>22
- aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
- i++
- }
-
- // round 3
- for i < 48 {
- alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1
- s := _r[i]
- alpha = (alpha<<s | alpha>>(32-s)) + e
- beta = c<<10 | c>>22
- a, b, c, d, e = e, alpha, b, beta, d
-
- // parallel line
- alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3
- s = r_[i]
- alpha = (alpha<<s | alpha>>(32-s)) + ee
- beta = cc<<10 | cc>>22
- aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
- i++
- }
-
- // round 4
- for i < 64 {
- alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc
- s := _r[i]
- alpha = (alpha<<s | alpha>>(32-s)) + e
- beta = c<<10 | c>>22
- a, b, c, d, e = e, alpha, b, beta, d
-
- // parallel line
- alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9
- s = r_[i]
- alpha = (alpha<<s | alpha>>(32-s)) + ee
- beta = cc<<10 | cc>>22
- aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
- i++
- }
-
- // round 5
- for i < 80 {
- alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e
- s := _r[i]
- alpha = (alpha<<s | alpha>>(32-s)) + e
- beta = c<<10 | c>>22
- a, b, c, d, e = e, alpha, b, beta, d
-
- // parallel line
- alpha = aa + (bb ^ cc ^ dd) + x[n_[i]]
- s = r_[i]
- alpha = (alpha<<s | alpha>>(32-s)) + ee
- beta = cc<<10 | cc>>22
- aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
- i++
- }
-
- // combine results
- dd += c + md.s[1]
- md.s[1] = md.s[2] + d + ee
- md.s[2] = md.s[3] + e + aa
- md.s[3] = md.s[4] + a + bb
- md.s[4] = md.s[0] + b + cc
- md.s[0] = dd
-
- p = p[BlockSize:]
- n += BlockSize
- }
- return n
-}
diff --git a/libgo/go/crypto/tls/root_stub.go b/libgo/go/crypto/tls/root_stub.go
index d00493a5736..ee2c3e01795 100644
--- a/libgo/go/crypto/tls/root_stub.go
+++ b/libgo/go/crypto/tls/root_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build plan9 darwin/nocgo
+// +build plan9 darwin,!cgo
package tls
diff --git a/libgo/go/crypto/twofish/twofish.go b/libgo/go/crypto/twofish/twofish.go
deleted file mode 100644
index 0616e7b8286..00000000000
--- a/libgo/go/crypto/twofish/twofish.go
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
-package twofish
-
-// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
-
-// This code is a port of the LibTom C implementation.
-// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
-// LibTomCrypt is free for all purposes under the public domain.
-// It was heavily inspired by the go blowfish package.
-
-import "strconv"
-
-// BlockSize is the constant block size of Twofish.
-const BlockSize = 16
-
-const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
-const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
-
-// A Cipher is an instance of Twofish encryption using a particular key.
-type Cipher struct {
- s [4][256]uint32
- k [40]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
- return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Twofish key, 16, 24 or 32 bytes.
-func NewCipher(key []byte) (*Cipher, error) {
- keylen := len(key)
-
- if keylen != 16 && keylen != 24 && keylen != 32 {
- return nil, KeySizeError(keylen)
- }
-
- // k is the number of 64 bit words in key
- k := keylen / 8
-
- // Create the S[..] words
- var S [4 * 4]byte
- for i := 0; i < k; i++ {
- // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
- for j, rsRow := range rs {
- for k, rsVal := range rsRow {
- S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
- }
- }
- }
-
- // Calculate subkeys
- c := new(Cipher)
- var tmp [4]byte
- for i := byte(0); i < 20; i++ {
- // A = h(p * 2x, Me)
- for j := range tmp {
- tmp[j] = 2 * i
- }
- A := h(tmp[:], key, 0)
-
- // B = rolc(h(p * (2x + 1), Mo), 8)
- for j := range tmp {
- tmp[j] = 2*i + 1
- }
- B := h(tmp[:], key, 1)
- B = rol(B, 8)
-
- c.k[2*i] = A + B
-
- // K[2i+1] = (A + 2B) <<< 9
- c.k[2*i+1] = rol(2*B+A, 9)
- }
-
- // Calculate sboxes
- switch k {
- case 2:
- for i := range c.s[0] {
- c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
- c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
- c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
- c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
- }
- case 3:
- for i := range c.s[0] {
- c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
- c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
- c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
- c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
- }
- default:
- for i := range c.s[0] {
- c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
- c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
- c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
- c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
- }
- }
-
- return c, nil
-}
-
-// Reset zeros the key data, so that it will no longer appear in the process's
-// memory.
-func (c *Cipher) Reset() {
- for i := range c.k {
- c.k[i] = 0
- }
- for i := range c.s {
- for j := 0; j < 256; j++ {
- c.s[i][j] = 0
- }
- }
-}
-
-// BlockSize returns the Twofish block size, 16 bytes.
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// store32l stores src in dst in little-endian form.
-func store32l(dst []byte, src uint32) {
- dst[0] = byte(src)
- dst[1] = byte(src >> 8)
- dst[2] = byte(src >> 16)
- dst[3] = byte(src >> 24)
- return
-}
-
-// load32l reads a little-endian uint32 from src.
-func load32l(src []byte) uint32 {
- return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
-}
-
-// rol returns x after a left circular rotation of y bits.
-func rol(x, y uint32) uint32 {
- return (x << (y & 31)) | (x >> (32 - (y & 31)))
-}
-
-// ror returns x after a right circular rotation of y bits.
-func ror(x, y uint32) uint32 {
- return (x >> (y & 31)) | (x << (32 - (y & 31)))
-}
-
-// The RS matrix. See [TWOFISH] 4.3
-var rs = [4][8]byte{
- {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
- {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
- {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
- {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
-}
-
-// sbox tables
-var sbox = [2][256]byte{
- {
- 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
- 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
- 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
- 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
- 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
- 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
- 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
- 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
- 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
- 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
- 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
- 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
- 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
- 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
- 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
- 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
- },
- {
- 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
- 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
- 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
- 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
- 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
- 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
- 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
- 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
- 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
- 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
- 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
- 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
- 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
- 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
- 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
- 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
- },
-}
-
-// gfMult returns a·b in GF(2^8)/p
-func gfMult(a, b byte, p uint32) byte {
- B := [2]uint32{0, uint32(b)}
- P := [2]uint32{0, p}
- var result uint32
-
- // branchless GF multiplier
- for i := 0; i < 7; i++ {
- result ^= B[a&1]
- a >>= 1
- B[1] = P[B[1]>>7] ^ (B[1] << 1)
- }
- result ^= B[a&1]
- return byte(result)
-}
-
-// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
-func mdsColumnMult(in byte, col int) uint32 {
- mul01 := in
- mul5B := gfMult(in, 0x5B, mdsPolynomial)
- mulEF := gfMult(in, 0xEF, mdsPolynomial)
-
- switch col {
- case 0:
- return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
- case 1:
- return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
- case 2:
- return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
- case 3:
- return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
- }
-
- panic("unreachable")
-}
-
-// h implements the S-box generation function. See [TWOFISH] 4.3.5
-func h(in, key []byte, offset int) uint32 {
- var y [4]byte
- for x := range y {
- y[x] = in[x]
- }
- switch len(key) / 8 {
- case 4:
- y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
- y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
- y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
- y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
- fallthrough
- case 3:
- y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
- y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
- y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
- y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
- fallthrough
- case 2:
- y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
- y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
- y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
- y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
- }
- // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
- var mdsMult uint32
- for i := range y {
- mdsMult ^= mdsColumnMult(y[i], i)
- }
- return mdsMult
-}
-
-// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
- S1 := c.s[0]
- S2 := c.s[1]
- S3 := c.s[2]
- S4 := c.s[3]
-
- // Load input
- ia := load32l(src[0:4])
- ib := load32l(src[4:8])
- ic := load32l(src[8:12])
- id := load32l(src[12:16])
-
- // Pre-whitening
- ia ^= c.k[0]
- ib ^= c.k[1]
- ic ^= c.k[2]
- id ^= c.k[3]
-
- for i := 0; i < 8; i++ {
- k := c.k[8+i*4 : 12+i*4]
- t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
- t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
- ic = ror(ic^(t1+k[0]), 1)
- id = rol(id, 1) ^ (t2 + t1 + k[1])
-
- t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
- t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
- ia = ror(ia^(t1+k[2]), 1)
- ib = rol(ib, 1) ^ (t2 + t1 + k[3])
- }
-
- // Output with "undo last swap"
- ta := ic ^ c.k[4]
- tb := id ^ c.k[5]
- tc := ia ^ c.k[6]
- td := ib ^ c.k[7]
-
- store32l(dst[0:4], ta)
- store32l(dst[4:8], tb)
- store32l(dst[8:12], tc)
- store32l(dst[12:16], td)
-}
-
-// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
-func (c *Cipher) Decrypt(dst, src []byte) {
- S1 := c.s[0]
- S2 := c.s[1]
- S3 := c.s[2]
- S4 := c.s[3]
-
- // Load input
- ta := load32l(src[0:4])
- tb := load32l(src[4:8])
- tc := load32l(src[8:12])
- td := load32l(src[12:16])
-
- // Undo undo final swap
- ia := tc ^ c.k[6]
- ib := td ^ c.k[7]
- ic := ta ^ c.k[4]
- id := tb ^ c.k[5]
-
- for i := 8; i > 0; i-- {
- k := c.k[4+i*4 : 8+i*4]
- t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
- t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
- ia = rol(ia, 1) ^ (t1 + k[2])
- ib = ror(ib^(t2+t1+k[3]), 1)
-
- t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
- t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
- ic = rol(ic, 1) ^ (t1 + k[0])
- id = ror(id^(t2+t1+k[1]), 1)
- }
-
- // Undo pre-whitening
- ia ^= c.k[0]
- ib ^= c.k[1]
- ic ^= c.k[2]
- id ^= c.k[3]
-
- store32l(dst[0:4], ia)
- store32l(dst[4:8], ib)
- store32l(dst[8:12], ic)
- store32l(dst[12:16], id)
-}
diff --git a/libgo/go/crypto/twofish/twofish_test.go b/libgo/go/crypto/twofish/twofish_test.go
deleted file mode 100644
index 303081f3f28..00000000000
--- a/libgo/go/crypto/twofish/twofish_test.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package twofish
-
-import (
- "bytes"
- "testing"
-)
-
-var qbox = [2][4][16]byte{
- {
- {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
- {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
- {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
- {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
- },
- {
- {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
- {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
- {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
- {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
- },
-}
-
-// genSbox generates the variable sbox
-func genSbox(qi int, x byte) byte {
- a0, b0 := x/16, x%16
- for i := 0; i < 2; i++ {
- a1 := a0 ^ b0
- b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
- a0 = qbox[qi][2*i][a1]
- b0 = qbox[qi][2*i+1][b1]
- }
- return (b0 << 4) + a0
-}
-
-func TestSbox(t *testing.T) {
- for n := range sbox {
- for m := range sbox[n] {
- if genSbox(n, byte(m)) != sbox[n][m] {
- t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
- }
- }
- }
-}
-
-var testVectors = []struct {
- key []byte
- dec []byte
- enc []byte
-}{
- // These tests are extracted from LibTom
- {
- []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
- []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
- []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
- },
- {
- []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
- 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
- []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
- []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
- },
- {
- []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
- 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
- []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
- []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
- },
- // These test are derived from http://www.schneier.com/code/ecb_ival.txt
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
- },
- {
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- },
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
- },
- {
- []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
- },
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
- },
-}
-
-func TestCipher(t *testing.T) {
- for n, tt := range testVectors {
- // Test if the plaintext (dec) is encrypts to the given
- // ciphertext (enc) using the given key. Test also if enc can
- // be decrypted again into dec.
- c, err := NewCipher(tt.key)
- if err != nil {
- t.Errorf("#%d: NewCipher: %v", n, err)
- return
- }
-
- buf := make([]byte, 16)
- c.Encrypt(buf, tt.dec)
- if !bytes.Equal(buf, tt.enc) {
- t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
- }
- c.Decrypt(buf, tt.enc)
- if !bytes.Equal(buf, tt.dec) {
- t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
- }
-
- // Test that 16 zero bytes, encrypted 1000 times then decrypted
- // 1000 times results in zero bytes again.
- zero := make([]byte, 16)
- buf = make([]byte, 16)
- for i := 0; i < 1000; i++ {
- c.Encrypt(buf, buf)
- }
- for i := 0; i < 1000; i++ {
- c.Decrypt(buf, buf)
- }
- if !bytes.Equal(buf, zero) {
- t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
- }
- }
-}
diff --git a/libgo/go/crypto/xtea/block.go b/libgo/go/crypto/xtea/block.go
deleted file mode 100644
index bf5d245992d..00000000000
--- a/libgo/go/crypto/xtea/block.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- Implementation adapted from Needham and Wheeler's paper:
- http://www.cix.co.uk/~klockstone/xtea.pdf
-
- A precalculated look up table is used during encryption/decryption for values that are based purely on the key.
-*/
-
-package xtea
-
-// XTEA is based on 64 rounds.
-const numRounds = 64
-
-// blockToUint32 reads an 8 byte slice into two uint32s.
-// The block is treated as big endian.
-func blockToUint32(src []byte) (uint32, uint32) {
- r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
- return r0, r1
-}
-
-// uint32ToBlock writes two uint32s into an 8 byte data block.
-// Values are written as big endian.
-func uint32ToBlock(v0, v1 uint32, dst []byte) {
- dst[0] = byte(v0 >> 24)
- dst[1] = byte(v0 >> 16)
- dst[2] = byte(v0 >> 8)
- dst[3] = byte(v0)
- dst[4] = byte(v1 >> 24)
- dst[5] = byte(v1 >> 16)
- dst[6] = byte(v1 >> 8)
- dst[7] = byte(v1 >> 0)
-}
-
-// encryptBlock encrypts a single 8 byte block using XTEA.
-func encryptBlock(c *Cipher, dst, src []byte) {
- v0, v1 := blockToUint32(src)
-
- // Two rounds of XTEA applied per loop
- for i := 0; i < numRounds; {
- v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
- i++
- v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
- i++
- }
-
- uint32ToBlock(v0, v1, dst)
-}
-
-// decryptBlock decrypt a single 8 byte block using XTEA.
-func decryptBlock(c *Cipher, dst, src []byte) {
- v0, v1 := blockToUint32(src)
-
- // Two rounds of XTEA applied per loop
- for i := numRounds; i > 0; {
- i--
- v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
- i--
- v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
- }
-
- uint32ToBlock(v0, v1, dst)
-}
diff --git a/libgo/go/crypto/xtea/cipher.go b/libgo/go/crypto/xtea/cipher.go
deleted file mode 100644
index 3ed05814a3b..00000000000
--- a/libgo/go/crypto/xtea/cipher.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
-// 1997 technical report, "Tea extensions."
-package xtea
-
-// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
-
-import "strconv"
-
-// The XTEA block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of an XTEA cipher using a particular key.
-// table contains a series of precalculated values that are used each round.
-type Cipher struct {
- table [64]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
- return "crypto/xtea: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a new Cipher.
-// The key argument should be the XTEA key.
-// XTEA only supports 128 bit (16 byte) keys.
-func NewCipher(key []byte) (*Cipher, error) {
- k := len(key)
- switch k {
- default:
- return nil, KeySizeError(k)
- case 16:
- break
- }
-
- c := new(Cipher)
- initCipher(c, key)
-
- return c, nil
-}
-
-// BlockSize returns the XTEA block size, 8 bytes.
-// It is necessary to satisfy the Block interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) }
-
-// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) }
-
-// Reset zeros the table, so that it will no longer appear in the process's memory.
-func (c *Cipher) Reset() {
- for i := 0; i < len(c.table); i++ {
- c.table[i] = 0
- }
-}
-
-// initCipher initializes the cipher context by creating a look up table
-// of precalculated values that are based on the key.
-func initCipher(c *Cipher, key []byte) {
- // Load the key into four uint32s
- var k [4]uint32
- for i := 0; i < len(k); i++ {
- j := i << 2 // Multiply by 4
- k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3])
- }
-
- // Precalculate the table
- const delta = 0x9E3779B9
- var sum uint32 = 0
-
- // Two rounds of XTEA applied per loop
- for i := 0; i < numRounds; {
- c.table[i] = sum + k[sum&3]
- i++
- sum += delta
- c.table[i] = sum + k[(sum>>11)&3]
- i++
- }
-}
diff --git a/libgo/go/crypto/xtea/xtea_test.go b/libgo/go/crypto/xtea/xtea_test.go
deleted file mode 100644
index 217d96adc20..00000000000
--- a/libgo/go/crypto/xtea/xtea_test.go
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package xtea
-
-import (
- "testing"
-)
-
-// A sample test key for when we just want to initialize a cipher
-var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
-
-// Test that the block size for XTEA is correct
-func TestBlocksize(t *testing.T) {
- if BlockSize != 8 {
- t.Errorf("BlockSize constant - expected 8, got %d", BlockSize)
- return
- }
-
- c, err := NewCipher(testKey)
- if err != nil {
- t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
- return
- }
-
- result := c.BlockSize()
- if result != 8 {
- t.Errorf("BlockSize function - expected 8, got %d", result)
- return
- }
-}
-
-// A series of test values to confirm that the Cipher.table array was initialized correctly
-var testTable = []uint32{
- 0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917,
- 0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F,
- 0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67,
- 0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F,
- 0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7,
- 0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF,
- 0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7,
- 0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB,
-}
-
-// Test that the cipher context is initialized correctly
-func TestCipherInit(t *testing.T) {
- c, err := NewCipher(testKey)
- if err != nil {
- t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
- return
- }
-
- for i := 0; i < len(c.table); i++ {
- if c.table[i] != testTable[i] {
- t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i])
- break
- }
- }
-}
-
-// Test that invalid key sizes return an error
-func TestInvalidKeySize(t *testing.T) {
- // Test a long key
- key := []byte{
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
- }
-
- _, err := NewCipher(key)
- if err == nil {
- t.Errorf("Invalid key size %d didn't result in an error.", len(key))
- }
-
- // Test a short key
- key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
-
- _, err = NewCipher(key)
- if err == nil {
- t.Errorf("Invalid key size %d didn't result in an error.", len(key))
- }
-}
-
-// Test that we can correctly decode some bytes we have encoded
-func TestEncodeDecode(t *testing.T) {
- original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}
- input := original
- output := make([]byte, BlockSize)
-
- c, err := NewCipher(testKey)
- if err != nil {
- t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
- return
- }
-
- // Encrypt the input block
- c.Encrypt(output, input)
-
- // Check that the output does not match the input
- differs := false
- for i := 0; i < len(input); i++ {
- if output[i] != input[i] {
- differs = true
- break
- }
- }
- if differs == false {
- t.Error("Cipher.Encrypt: Failed to encrypt the input block.")
- return
- }
-
- // Decrypt the block we just encrypted
- input = output
- output = make([]byte, BlockSize)
- c.Decrypt(output, input)
-
- // Check that the output from decrypt matches our initial input
- for i := 0; i < len(input); i++ {
- if output[i] != original[i] {
- t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i])
- return
- }
- }
-}
-
-// Test Vectors
-type CryptTest struct {
- key []byte
- plainText []byte
- cipherText []byte
-}
-
-var CryptTests = []CryptTest{
- // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors
- {
- []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
- []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
- []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5},
- },
- {
- []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
- []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
- []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8},
- },
- {
- []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
- []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f},
- []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
- },
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
- []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5},
- },
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
- []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d},
- },
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55},
- []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
- },
-
- // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9},
- },
- {
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
- []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16},
- },
- {
- []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
- []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64},
- },
- {
- []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
- []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
- []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD},
- },
-}
-
-// Test encryption
-func TestCipherEncrypt(t *testing.T) {
- for i, tt := range CryptTests {
- c, err := NewCipher(tt.key)
- if err != nil {
- t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
- continue
- }
-
- out := make([]byte, len(tt.plainText))
- c.Encrypt(out, tt.plainText)
-
- for j := 0; j < len(out); j++ {
- if out[j] != tt.cipherText[j] {
- t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j])
- break
- }
- }
- }
-}
-
-// Test decryption
-func TestCipherDecrypt(t *testing.T) {
- for i, tt := range CryptTests {
- c, err := NewCipher(tt.key)
- if err != nil {
- t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
- continue
- }
-
- out := make([]byte, len(tt.cipherText))
- c.Decrypt(out, tt.cipherText)
-
- for j := 0; j < len(out); j++ {
- if out[j] != tt.plainText[j] {
- t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j])
- break
- }
- }
- }
-}
-
-// Test resetting the cipher context
-func TestReset(t *testing.T) {
- c, err := NewCipher(testKey)
- if err != nil {
- t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
- return
- }
-
- c.Reset()
- for i := 0; i < len(c.table); i++ {
- if c.table[i] != 0 {
- t.Errorf("Cipher.Reset: Failed to clear Cipher.table[%d]. expected 0, got %08X", i, c.table[i])
- return
- }
- }
-}
diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go
index 9835e38de7e..e80420e5bb3 100644
--- a/libgo/go/database/sql/convert.go
+++ b/libgo/go/database/sql/convert.go
@@ -40,6 +40,9 @@ func convertAssign(dest, src interface{}) error {
case *string:
*d = s
return nil
+ case *[]byte:
+ *d = []byte(s)
+ return nil
}
case []byte:
switch d := dest.(type) {
@@ -50,6 +53,12 @@ func convertAssign(dest, src interface{}) error {
*d = s
return nil
}
+ case nil:
+ switch d := dest.(type) {
+ case *[]byte:
+ *d = nil
+ return nil
+ }
}
var sv reflect.Value
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index b0d137cd715..df25023e127 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -585,12 +585,26 @@ func converterForType(typ string) driver.ValueConverter {
switch typ {
case "bool":
return driver.Bool
+ case "nullbool":
+ return driver.Null{driver.Bool}
case "int32":
return driver.Int32
case "string":
return driver.NotNull{driver.String}
case "nullstring":
return driver.Null{driver.String}
+ case "int64":
+ // TODO(coopernurse): add type-specific converter
+ return driver.NotNull{driver.DefaultParameterConverter}
+ case "nullint64":
+ // TODO(coopernurse): add type-specific converter
+ return driver.Null{driver.DefaultParameterConverter}
+ case "float64":
+ // TODO(coopernurse): add type-specific converter
+ return driver.NotNull{driver.DefaultParameterConverter}
+ case "nullfloat64":
+ // TODO(coopernurse): add type-specific converter
+ return driver.Null{driver.DefaultParameterConverter}
case "datetime":
return driver.DefaultParameterConverter
}
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index a8bf2a8b00c..34a76521050 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -47,7 +47,6 @@ type RawBytes []byte
// // NULL value
// }
//
-// TODO(bradfitz): add other types.
type NullString struct {
String string
Valid bool // Valid is true if String is not NULL
@@ -71,6 +70,84 @@ func (ns NullString) SubsetValue() (interface{}, error) {
return ns.String, nil
}
+// NullInt64 represents an int64 that may be null.
+// NullInt64 implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullInt64 struct {
+ Int64 int64
+ Valid bool // Valid is true if Int64 is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullInt64) ScanInto(value interface{}) error {
+ if value == nil {
+ n.Int64, n.Valid = 0, false
+ return nil
+ }
+ n.Valid = true
+ return convertAssign(&n.Int64, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullInt64) SubsetValue() (interface{}, error) {
+ if !n.Valid {
+ return nil, nil
+ }
+ return n.Int64, nil
+}
+
+// NullFloat64 represents a float64 that may be null.
+// NullFloat64 implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullFloat64 struct {
+ Float64 float64
+ Valid bool // Valid is true if Float64 is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullFloat64) ScanInto(value interface{}) error {
+ if value == nil {
+ n.Float64, n.Valid = 0, false
+ return nil
+ }
+ n.Valid = true
+ return convertAssign(&n.Float64, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullFloat64) SubsetValue() (interface{}, error) {
+ if !n.Valid {
+ return nil, nil
+ }
+ return n.Float64, nil
+}
+
+// NullBool represents a bool that may be null.
+// NullBool implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullBool struct {
+ Bool bool
+ Valid bool // Valid is true if Bool is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullBool) ScanInto(value interface{}) error {
+ if value == nil {
+ n.Bool, n.Valid = false, false
+ return nil
+ }
+ n.Valid = true
+ return convertAssign(&n.Bool, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullBool) SubsetValue() (interface{}, error) {
+ if !n.Valid {
+ return nil, nil
+ }
+ return n.Bool, nil
+}
+
// ScannerInto is an interface used by Scan.
type ScannerInto interface {
// ScanInto assigns a value from a database driver.
@@ -479,8 +556,11 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
if err != nil {
return nil, err
}
- defer stmt.Close()
- return stmt.Query(args...)
+ rows, err := stmt.Query(args...)
+ if err == nil {
+ rows.closeStmt = stmt
+ }
+ return rows, err
}
// QueryRow executes a query that is expected to return at most one row.
@@ -824,6 +904,12 @@ func (rs *Rows) Scan(dest ...interface{}) error {
if !ok {
continue
}
+ if *b == nil {
+ // If the []byte is now nil (for a NULL value),
+ // don't fall through to below which would
+ // turn it into a non-nil 0-length byte slice
+ continue
+ }
if _, ok = dp.(*RawBytes); ok {
continue
}
@@ -865,17 +951,10 @@ func (r *Row) Scan(dest ...interface{}) error {
if r.err != nil {
return r.err
}
- defer r.rows.Close()
- if !r.rows.Next() {
- return ErrNoRows
- }
- err := r.rows.Scan(dest...)
- if err != nil {
- return err
- }
// TODO(bradfitz): for now we need to defensively clone all
- // []byte that the driver returned, since we're about to close
+ // []byte that the driver returned (not permitting
+ // *RawBytes in Rows.Scan), since we're about to close
// the Rows in our defer, when we return from this function.
// the contract with the driver.Next(...) interface is that it
// can return slices into read-only temporary memory that's
@@ -890,14 +969,17 @@ func (r *Row) Scan(dest ...interface{}) error {
if _, ok := dp.(*RawBytes); ok {
return errors.New("sql: RawBytes isn't allowed on Row.Scan")
}
- b, ok := dp.(*[]byte)
- if !ok {
- continue
- }
- clone := make([]byte, len(*b))
- copy(clone, *b)
- *b = clone
}
+
+ defer r.rows.Close()
+ if !r.rows.Next() {
+ return ErrNoRows
+ }
+ err := r.rows.Scan(dest...)
+ if err != nil {
+ return err
+ }
+
return nil
}
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index 3fe93986faa..c5cadad8499 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -5,6 +5,7 @@
package sql
import (
+ "fmt"
"reflect"
"strings"
"testing"
@@ -310,6 +311,40 @@ func TestTxStmt(t *testing.T) {
}
}
+// Issue: http://golang.org/issue/2784
+// This test didn't fail before because we got luckly with the fakedb driver.
+// It was failing, and now not, in github.com/bradfitz/go-sql-test
+func TestTxQuery(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+ exec(t, db, "INSERT|t1|name=Alice")
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer tx.Rollback()
+
+ r, err := tx.Query("SELECT|t1|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !r.Next() {
+ if r.Err() != nil {
+ t.Fatal(r.Err())
+ }
+ t.Fatal("expected one row")
+ }
+
+ var x string
+ err = r.Scan(&x)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
// Tests fix for issue 2542, that we release a lock when querying on
// a closed connection.
func TestIssue2542Deadlock(t *testing.T) {
@@ -323,6 +358,34 @@ func TestIssue2542Deadlock(t *testing.T) {
}
}
+// Tests fix for issue 2788, that we bind nil to a []byte if the
+// value in the column is sql null
+func TestNullByteSlice(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t|id=int32,name=nullstring")
+ exec(t, db, "INSERT|t|id=10,name=?", nil)
+
+ var name []byte
+
+ err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if name != nil {
+ t.Fatalf("name []byte should be nil for null column value, got: %#v", name)
+ }
+
+ exec(t, db, "INSERT|t|id=11,name=?", "bob")
+ err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(name) != "bob" {
+ t.Fatalf("name []byte should be bob, got: %q", string(name))
+ }
+}
+
func TestQueryRowClosingStmt(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
@@ -341,64 +404,116 @@ func TestQueryRowClosingStmt(t *testing.T) {
}
}
+type nullTestRow struct {
+ nullParam interface{}
+ notNullParam interface{}
+ scanNullVal interface{}
+}
+
+type nullTestSpec struct {
+ nullType string
+ notNullType string
+ rows [6]nullTestRow
+}
+
func TestNullStringParam(t *testing.T) {
+ spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
+ nullTestRow{NullString{"aqua", true}, "", NullString{"aqua", true}},
+ nullTestRow{NullString{"brown", false}, "", NullString{"", false}},
+ nullTestRow{"chartreuse", "", NullString{"chartreuse", true}},
+ nullTestRow{NullString{"darkred", true}, "", NullString{"darkred", true}},
+ nullTestRow{NullString{"eel", false}, "", NullString{"", false}},
+ nullTestRow{"foo", NullString{"black", false}, nil},
+ }}
+ nullTestRun(t, spec)
+}
+
+func TestNullInt64Param(t *testing.T) {
+ spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{
+ nullTestRow{NullInt64{31, true}, 1, NullInt64{31, true}},
+ nullTestRow{NullInt64{-22, false}, 1, NullInt64{0, false}},
+ nullTestRow{22, 1, NullInt64{22, true}},
+ nullTestRow{NullInt64{33, true}, 1, NullInt64{33, true}},
+ nullTestRow{NullInt64{222, false}, 1, NullInt64{0, false}},
+ nullTestRow{0, NullInt64{31, false}, nil},
+ }}
+ nullTestRun(t, spec)
+}
+
+func TestNullFloat64Param(t *testing.T) {
+ spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
+ nullTestRow{NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
+ nullTestRow{NullFloat64{13.1, false}, 1, NullFloat64{0, false}},
+ nullTestRow{-22.9, 1, NullFloat64{-22.9, true}},
+ nullTestRow{NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}},
+ nullTestRow{NullFloat64{222, false}, 1, NullFloat64{0, false}},
+ nullTestRow{10, NullFloat64{31.2, false}, nil},
+ }}
+ nullTestRun(t, spec)
+}
+
+func TestNullBoolParam(t *testing.T) {
+ spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{
+ nullTestRow{NullBool{false, true}, true, NullBool{false, true}},
+ nullTestRow{NullBool{true, false}, false, NullBool{false, false}},
+ nullTestRow{true, true, NullBool{true, true}},
+ nullTestRow{NullBool{true, true}, false, NullBool{true, true}},
+ nullTestRow{NullBool{true, false}, true, NullBool{false, false}},
+ nullTestRow{true, NullBool{true, false}, nil},
+ }}
+ nullTestRun(t, spec)
+}
+
+func nullTestRun(t *testing.T, spec nullTestSpec) {
db := newTestDB(t, "")
defer closeDB(t, db)
- exec(t, db, "CREATE|t|id=int32,name=string,favcolor=nullstring")
+ exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType))
// Inserts with db.Exec:
- exec(t, db, "INSERT|t|id=?,name=?,favcolor=?", 1, "alice", NullString{"aqua", true})
- exec(t, db, "INSERT|t|id=?,name=?,favcolor=?", 2, "bob", NullString{"brown", false})
-
- _, err := db.Exec("INSERT|t|id=?,name=?,favcolor=?", 999, nil, nil)
- if err == nil {
- // TODO: this test fails, but it's just because
- // fakeConn implements the optional Execer interface,
- // so arguably this is the correct behavior. But
- // maybe I should flesh out the fakeConn.Exec
- // implementation so this properly fails.
- // t.Errorf("expected error inserting nil name with Exec")
- }
+ exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam)
+ exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam)
// Inserts with a prepared statement:
- stmt, err := db.Prepare("INSERT|t|id=?,name=?,favcolor=?")
+ stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
if err != nil {
t.Fatalf("prepare: %v", err)
}
- if _, err := stmt.Exec(3, "chris", "chartreuse"); err != nil {
+ if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil {
t.Errorf("exec insert chris: %v", err)
}
- if _, err := stmt.Exec(4, "dave", NullString{"darkred", true}); err != nil {
+ if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil {
t.Errorf("exec insert dave: %v", err)
}
- if _, err := stmt.Exec(5, "eleanor", NullString{"eel", false}); err != nil {
- t.Errorf("exec insert dave: %v", err)
+ if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil {
+ t.Errorf("exec insert eleanor: %v", err)
}
- // Can't put null name into non-nullstring column,
- if _, err := stmt.Exec(5, NullString{"", false}, nil); err == nil {
- t.Errorf("expected error inserting nil name with prepared statement Exec")
+ // Can't put null val into non-null col
+ if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil {
+ t.Errorf("expected error inserting nil val with prepared statement Exec")
}
- type nameColor struct {
- name string
- favColor NullString
+ _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
+ if err == nil {
+ // TODO: this test fails, but it's just because
+ // fakeConn implements the optional Execer interface,
+ // so arguably this is the correct behavior. But
+ // maybe I should flesh out the fakeConn.Exec
+ // implementation so this properly fails.
+ // t.Errorf("expected error inserting nil name with Exec")
}
- wantMap := map[int]nameColor{
- 1: nameColor{"alice", NullString{"aqua", true}},
- 2: nameColor{"bob", NullString{"", false}},
- 3: nameColor{"chris", NullString{"chartreuse", true}},
- 4: nameColor{"dave", NullString{"darkred", true}},
- 5: nameColor{"eleanor", NullString{"", false}},
- }
- for id, want := range wantMap {
- var got nameColor
- if err := db.QueryRow("SELECT|t|name,favcolor|id=?", id).Scan(&got.name, &got.favColor); err != nil {
+ paramtype := reflect.TypeOf(spec.rows[0].nullParam)
+ bindVal := reflect.New(paramtype).Interface()
+
+ for i := 0; i < 5; i++ {
+ id := i + 1
+ if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil {
t.Errorf("id=%d Scan: %v", id, err)
}
- if got != want {
- t.Errorf("id=%d got %#v, want %#v", id, got, want)
+ bindValDeref := reflect.ValueOf(bindVal).Elem().Interface()
+ if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) {
+ t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal)
}
}
}
diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go
index d4872eea2c5..b756afdd040 100644
--- a/libgo/go/encoding/binary/varint.go
+++ b/libgo/go/encoding/binary/varint.go
@@ -37,6 +37,7 @@ const (
)
// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutUvarint will panic.
func PutUvarint(buf []byte, x uint64) int {
i := 0
for x >= 0x80 {
@@ -73,6 +74,7 @@ func Uvarint(buf []byte) (uint64, int) {
}
// PutVarint encodes an int64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutVarint will panic.
func PutVarint(buf []byte, x int64) int {
ux := uint64(x) << 1
if x < 0 {
@@ -98,14 +100,6 @@ func Varint(buf []byte) (int64, int) {
return x, n
}
-// WriteUvarint encodes x and writes the result to w.
-func WriteUvarint(w io.Writer, x uint64) error {
- var buf [MaxVarintLen64]byte
- n := PutUvarint(buf[:], x)
- _, err := w.Write(buf[0:n])
- return err
-}
-
var overflow = errors.New("binary: varint overflows a 64-bit integer")
// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
@@ -129,15 +123,6 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
panic("unreachable")
}
-// WriteVarint encodes x and writes the result to w.
-func WriteVarint(w io.Writer, x int64) error {
- ux := uint64(x) << 1
- if x < 0 {
- ux = ^ux
- }
- return WriteUvarint(w, ux)
-}
-
// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
func ReadVarint(r io.ByteReader) (int64, error) {
ux, err := ReadUvarint(r) // ok to continue in presence of error
diff --git a/libgo/go/encoding/binary/varint_test.go b/libgo/go/encoding/binary/varint_test.go
index dc550f22f44..9476bd5fb7a 100644
--- a/libgo/go/encoding/binary/varint_test.go
+++ b/libgo/go/encoding/binary/varint_test.go
@@ -25,9 +25,9 @@ func TestConstants(t *testing.T) {
}
func testVarint(t *testing.T, x int64) {
- buf1 := make([]byte, MaxVarintLen64)
- n := PutVarint(buf1[:], x)
- y, m := Varint(buf1[0:n])
+ buf := make([]byte, MaxVarintLen64)
+ n := PutVarint(buf, x)
+ y, m := Varint(buf[0:n])
if x != y {
t.Errorf("Varint(%d): got %d", x, y)
}
@@ -35,15 +35,7 @@ func testVarint(t *testing.T, x int64) {
t.Errorf("Varint(%d): got n = %d; want %d", x, m, n)
}
- var buf2 bytes.Buffer
- err := WriteVarint(&buf2, x)
- if err != nil {
- t.Errorf("WriteVarint(%d): %s", x, err)
- }
- if n != buf2.Len() {
- t.Errorf("WriteVarint(%d): got n = %d; want %d", x, buf2.Len(), n)
- }
- y, err = ReadVarint(&buf2)
+ y, err := ReadVarint(bytes.NewBuffer(buf))
if err != nil {
t.Errorf("ReadVarint(%d): %s", x, err)
}
@@ -53,9 +45,9 @@ func testVarint(t *testing.T, x int64) {
}
func testUvarint(t *testing.T, x uint64) {
- buf1 := make([]byte, MaxVarintLen64)
- n := PutUvarint(buf1[:], x)
- y, m := Uvarint(buf1[0:n])
+ buf := make([]byte, MaxVarintLen64)
+ n := PutUvarint(buf, x)
+ y, m := Uvarint(buf[0:n])
if x != y {
t.Errorf("Uvarint(%d): got %d", x, y)
}
@@ -63,15 +55,7 @@ func testUvarint(t *testing.T, x uint64) {
t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
}
- var buf2 bytes.Buffer
- err := WriteUvarint(&buf2, x)
- if err != nil {
- t.Errorf("WriteUvarint(%d): %s", x, err)
- }
- if n != buf2.Len() {
- t.Errorf("WriteUvarint(%d): got n = %d; want %d", x, buf2.Len(), n)
- }
- y, err = ReadUvarint(&buf2)
+ y, err := ReadUvarint(bytes.NewBuffer(buf))
if err != nil {
t.Errorf("ReadUvarint(%d): %s", x, err)
}
diff --git a/libgo/go/encoding/git85/git.go b/libgo/go/encoding/git85/git.go
deleted file mode 100644
index d383213ce87..00000000000
--- a/libgo/go/encoding/git85/git.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package git85 implements the radix 85 data encoding
-// used in the Git version control system.
-package git85
-
-import (
- "bytes"
- "io"
- "strconv"
-)
-
-type CorruptInputError int64
-
-func (e CorruptInputError) Error() string {
- return "illegal git85 data at input byte " + strconv.FormatInt(int64(e), 10)
-}
-
-const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
-
-// The decodings are 1+ the actual value, so that the
-// default zero value can be used to mean "not valid".
-var decode = [256]uint8{
- '0': 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- 'A': 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
- 'a': 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
- '!': 63,
- '#': 64, 65, 66, 67,
- '(': 68, 69, 70, 71,
- '-': 72,
- ';': 73,
- '<': 74, 75, 76, 77,
- '@': 78,
- '^': 79, 80, 81,
- '{': 82, 83, 84, 85,
-}
-
-// Encode encodes src into EncodedLen(len(src))
-// bytes of dst. As a convenience, it returns the number
-// of bytes written to dst, but this value is always EncodedLen(len(src)).
-// Encode implements the radix 85 encoding used in the
-// Git version control tool.
-//
-// The encoding splits src into chunks of at most 52 bytes
-// and encodes each chunk on its own line.
-func Encode(dst, src []byte) int {
- ndst := 0
- for len(src) > 0 {
- n := len(src)
- if n > 52 {
- n = 52
- }
- if n <= 27 {
- dst[ndst] = byte('A' + n - 1)
- } else {
- dst[ndst] = byte('a' + n - 26 - 1)
- }
- ndst++
- for i := 0; i < n; i += 4 {
- var v uint32
- for j := 0; j < 4 && i+j < n; j++ {
- v |= uint32(src[i+j]) << uint(24-j*8)
- }
- for j := 4; j >= 0; j-- {
- dst[ndst+j] = encode[v%85]
- v /= 85
- }
- ndst += 5
- }
- dst[ndst] = '\n'
- ndst++
- src = src[n:]
- }
- return ndst
-}
-
-// EncodedLen returns the length of an encoding of n source bytes.
-func EncodedLen(n int) int {
- if n == 0 {
- return 0
- }
- // 5 bytes per 4 bytes of input, rounded up.
- // 2 extra bytes for each line of 52 src bytes, rounded up.
- return (n+3)/4*5 + (n+51)/52*2
-}
-
-var newline = []byte{'\n'}
-
-// Decode decodes src into at most MaxDecodedLen(len(src))
-// bytes, returning the actual number of bytes written to dst.
-//
-// If Decode encounters invalid input, it returns a CorruptInputError.
-//
-func Decode(dst, src []byte) (n int, err error) {
- ndst := 0
- nsrc := 0
- for nsrc < len(src) {
- var l int
- switch ch := int(src[nsrc]); {
- case 'A' <= ch && ch <= 'Z':
- l = ch - 'A' + 1
- case 'a' <= ch && ch <= 'z':
- l = ch - 'a' + 26 + 1
- default:
- return ndst, CorruptInputError(nsrc)
- }
- if nsrc+1+l > len(src) {
- return ndst, CorruptInputError(nsrc)
- }
- el := (l + 3) / 4 * 5 // encoded len
- if nsrc+1+el+1 > len(src) || src[nsrc+1+el] != '\n' {
- return ndst, CorruptInputError(nsrc)
- }
- line := src[nsrc+1 : nsrc+1+el]
- for i := 0; i < el; i += 5 {
- var v uint32
- for j := 0; j < 5; j++ {
- ch := decode[line[i+j]]
- if ch == 0 {
- return ndst, CorruptInputError(nsrc + 1 + i + j)
- }
- v = v*85 + uint32(ch-1)
- }
- for j := 0; j < 4; j++ {
- dst[ndst] = byte(v >> 24)
- v <<= 8
- ndst++
- }
- }
- // Last fragment may have run too far (but there was room in dst).
- // Back up.
- if l%4 != 0 {
- ndst -= 4 - l%4
- }
- nsrc += 1 + el + 1
- }
- return ndst, nil
-}
-
-func MaxDecodedLen(n int) int { return n / 5 * 4 }
-
-// NewEncoder returns a new Git base85 stream encoder. Data written to
-// the returned writer will be encoded and then written to w.
-// The Git encoding operates on 52-byte blocks; when finished
-// writing, the caller must Close the returned encoder to flush any
-// partially written blocks.
-func NewEncoder(w io.Writer) io.WriteCloser { return &encoder{w: w} }
-
-type encoder struct {
- w io.Writer
- err error
- buf [52]byte
- nbuf int
- out [1024]byte
- nout int
-}
-
-func (e *encoder) Write(p []byte) (n int, err error) {
- if e.err != nil {
- return 0, e.err
- }
-
- // Leading fringe.
- if e.nbuf > 0 {
- var i int
- for i = 0; i < len(p) && e.nbuf < 52; i++ {
- e.buf[e.nbuf] = p[i]
- e.nbuf++
- }
- n += i
- p = p[i:]
- if e.nbuf < 52 {
- return
- }
- nout := Encode(e.out[0:], e.buf[0:])
- if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
- return n, e.err
- }
- e.nbuf = 0
- }
-
- // Large interior chunks.
- for len(p) >= 52 {
- nn := len(e.out) / (1 + 52/4*5 + 1) * 52
- if nn > len(p) {
- nn = len(p) / 52 * 52
- }
- if nn > 0 {
- nout := Encode(e.out[0:], p[0:nn])
- if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
- return n, e.err
- }
- }
- n += nn
- p = p[nn:]
- }
-
- // Trailing fringe.
- for i := 0; i < len(p); i++ {
- e.buf[i] = p[i]
- }
- e.nbuf = len(p)
- n += len(p)
- return
-}
-
-func (e *encoder) Close() error {
- // If there's anything left in the buffer, flush it out
- if e.err == nil && e.nbuf > 0 {
- nout := Encode(e.out[0:], e.buf[0:e.nbuf])
- e.nbuf = 0
- _, e.err = e.w.Write(e.out[0:nout])
- }
- return e.err
-}
-
-// NewDecoder returns a new Git base85 stream decoder.
-func NewDecoder(r io.Reader) io.Reader { return &decoder{r: r} }
-
-type decoder struct {
- r io.Reader
- err error
- readErr error
- buf [1024]byte
- nbuf int
- out []byte
- outbuf [1024]byte
- off int64
-}
-
-func (d *decoder) Read(p []byte) (n int, err error) {
- if len(p) == 0 {
- return 0, nil
- }
-
- for {
- // Copy leftover output from last decode.
- if len(d.out) > 0 {
- n = copy(p, d.out)
- d.out = d.out[n:]
- return
- }
-
- // Out of decoded output. Check errors.
- if d.err != nil {
- return 0, d.err
- }
- if d.readErr != nil {
- d.err = d.readErr
- return 0, d.err
- }
-
- // Read and decode more input.
- var nn int
- nn, d.readErr = d.r.Read(d.buf[d.nbuf:])
- d.nbuf += nn
-
- // Send complete lines to Decode.
- nl := bytes.LastIndex(d.buf[0:d.nbuf], newline)
- if nl < 0 {
- continue
- }
- nn, d.err = Decode(d.outbuf[0:], d.buf[0:nl+1])
- if e, ok := d.err.(CorruptInputError); ok {
- d.err = CorruptInputError(int64(e) + d.off)
- }
- d.out = d.outbuf[0:nn]
- d.nbuf = copy(d.buf[0:], d.buf[nl+1:d.nbuf])
- d.off += int64(nl + 1)
- }
- panic("unreachable")
-}
diff --git a/libgo/go/encoding/git85/git_test.go b/libgo/go/encoding/git85/git_test.go
deleted file mode 100644
index 81f5b0e3299..00000000000
--- a/libgo/go/encoding/git85/git_test.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package git85
-
-import (
- "bytes"
- "io"
- "io/ioutil"
- "testing"
-)
-
-type testpair struct {
- decoded, encoded string
-}
-
-func testEqual(t *testing.T, msg string, args ...interface{}) bool {
- if args[len(args)-2] != args[len(args)-1] {
- t.Errorf(msg, args...)
- return false
- }
- return true
-}
-
-func TestGitTable(t *testing.T) {
- var saw [256]bool
- for i, c := range encode {
- if decode[c] != uint8(i+1) {
- t.Errorf("decode['%c'] = %d, want %d", c, decode[c], i+1)
- }
- saw[c] = true
- }
- for i, b := range saw {
- if !b && decode[i] != 0 {
- t.Errorf("decode[%d] = %d, want 0", i, decode[i])
- }
- }
-}
-
-var gitPairs = []testpair{
- // Wikipedia example, adapted.
- {
- "Man is distinguished, not only by his reason, but by this singular passion from " +
- "other animals, which is a lust of the mind, that by a perseverance of delight in " +
- "the continued and indefatigable generation of knowledge, exceeds the short " +
- "vehemence of any carnal pleasure.",
-
- "zO<`^zX>%ZCX>)XGZfA9Ab7*B`EFf-gbRchTY<VDJc_3(Mb0BhMVRLV8EFfZabRc4R\n" +
- "zAarPHb0BkRZfA9DVR9gFVRLh7Z*CxFa&K)QZ**v7av))DX>DO_b1WctXlY|;AZc?T\n" +
- "zVIXXEb95kYW*~HEWgu;7Ze%PVbZB98AYyqSVIXj2a&u*NWpZI|V`U(3W*}r`Y-wj`\n" +
- "zbRcPNAarPDAY*TCbZKsNWn>^>Ze$>7Ze(R<VRUI{VPb4$AZKN6WpZJ3X>V>IZ)PBC\n" +
- "zZf|#NWn^b%EFfigV`XJzb0BnRWgv5CZ*p`Xc4cT~ZDnp_Wgu^6AYpEKAY);2ZeeU7\n" +
- "IaBO8^b9HiME&u=k\n",
- },
-}
-
-var gitBigtest = gitPairs[len(gitPairs)-1]
-
-func TestEncode(t *testing.T) {
- for _, p := range gitPairs {
- buf := make([]byte, EncodedLen(len(p.decoded)))
- n := Encode(buf, []byte(p.decoded))
- if n != len(buf) {
- t.Errorf("EncodedLen does not agree with Encode")
- }
- buf = buf[0:n]
- testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded)
- }
-}
-
-func TestEncoder(t *testing.T) {
- for _, p := range gitPairs {
- bb := &bytes.Buffer{}
- encoder := NewEncoder(bb)
- encoder.Write([]byte(p.decoded))
- encoder.Close()
- testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
- }
-}
-
-func TestEncoderBuffering(t *testing.T) {
- input := []byte(gitBigtest.decoded)
- for bs := 1; bs <= 12; bs++ {
- bb := &bytes.Buffer{}
- encoder := NewEncoder(bb)
- for pos := 0; pos < len(input); pos += bs {
- end := pos + bs
- if end > len(input) {
- end = len(input)
- }
- n, err := encoder.Write(input[pos:end])
- testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
- testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
- }
- err := encoder.Close()
- testEqual(t, "Close gave error %v, want %v", err, error(nil))
- testEqual(t, "Encoding/%d of %q = %q, want %q", bs, gitBigtest.decoded, bb.String(), gitBigtest.encoded)
- }
-}
-
-func TestDecode(t *testing.T) {
- for _, p := range gitPairs {
- dbuf := make([]byte, 4*len(p.encoded))
- ndst, err := Decode(dbuf, []byte(p.encoded))
- testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
- testEqual(t, "Decode(%q) = ndst %v, want %v", p.encoded, ndst, len(p.decoded))
- testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:ndst]), p.decoded)
- }
-}
-
-func TestDecoder(t *testing.T) {
- for _, p := range gitPairs {
- decoder := NewDecoder(bytes.NewBufferString(p.encoded))
- dbuf, err := ioutil.ReadAll(decoder)
- if err != nil {
- t.Fatal("Read failed", err)
- }
- testEqual(t, "Read from %q = length %v, want %v", p.encoded, len(dbuf), len(p.decoded))
- testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf), p.decoded)
- if err != nil {
- testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
- }
- }
-}
-
-func TestDecoderBuffering(t *testing.T) {
- for bs := 1; bs <= 12; bs++ {
- decoder := NewDecoder(bytes.NewBufferString(gitBigtest.encoded))
- buf := make([]byte, len(gitBigtest.decoded)+12)
- var total int
- for total = 0; total < len(gitBigtest.decoded); {
- n, err := decoder.Read(buf[total : total+bs])
- testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", gitBigtest.encoded, total, n, err, error(nil))
- total += n
- }
- testEqual(t, "Decoding/%d of %q = %q, want %q", bs, gitBigtest.encoded, string(buf[0:total]), gitBigtest.decoded)
- }
-}
-
-func TestDecodeCorrupt(t *testing.T) {
- type corrupt struct {
- e string
- p int
- }
- examples := []corrupt{
- {"v", 0},
- {"!z!!!!!!!!!", 0},
- }
-
- for _, e := range examples {
- dbuf := make([]byte, 2*len(e.e))
- _, err := Decode(dbuf, []byte(e.e))
- switch err := err.(type) {
- case CorruptInputError:
- testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
- default:
- t.Error("Decoder failed to detect corruption in", e)
- }
- }
-}
-
-func TestGitBig(t *testing.T) {
- n := 3*1000 + 1
- raw := make([]byte, n)
- const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
- for i := 0; i < n; i++ {
- raw[i] = alpha[i%len(alpha)]
- }
- encoded := new(bytes.Buffer)
- w := NewEncoder(encoded)
- nn, err := w.Write(raw)
- if nn != n || err != nil {
- t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
- }
- err = w.Close()
- if err != nil {
- t.Fatalf("Encoder.Close() = %v want nil", err)
- }
- decoded, err := ioutil.ReadAll(NewDecoder(encoded))
- if err != nil {
- t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
- }
-
- if !bytes.Equal(raw, decoded) {
- var i int
- for i = 0; i < len(decoded) && i < len(raw); i++ {
- if decoded[i] != raw[i] {
- break
- }
- }
- t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
- }
-}
diff --git a/libgo/go/encoding/gob/debug.go b/libgo/go/encoding/gob/debug.go
index 4a61d0fb2f8..6dc7fc9aca0 100644
--- a/libgo/go/encoding/gob/debug.go
+++ b/libgo/go/encoding/gob/debug.go
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Delete the next line to include this file in the gob package.
+// +build ignore
+
package gob
// This file is not normally included in the gob package. Used only for debugging the package itself.
diff --git a/libgo/go/encoding/gob/decoder.go b/libgo/go/encoding/gob/decoder.go
index 5e684d3ee7e..fb28c8caf53 100644
--- a/libgo/go/encoding/gob/decoder.go
+++ b/libgo/go/encoding/gob/decoder.go
@@ -75,7 +75,9 @@ func (dec *Decoder) recvMessage() bool {
dec.err = err
return false
}
- if nbytes >= 1<<31 {
+ // Upper limit of 1GB, allowing room to grow a little without overflow.
+ // TODO: We might want more control over this limit.
+ if nbytes >= 1<<30 {
dec.err = errBadCount
return false
}
diff --git a/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go
index b8dfeeb5156..83644c0331b 100644
--- a/libgo/go/encoding/gob/gobencdec_test.go
+++ b/libgo/go/encoding/gob/gobencdec_test.go
@@ -547,7 +547,6 @@ func (a isZeroBugArray) GobEncode() (b []byte, e error) {
}
func (a *isZeroBugArray) GobDecode(data []byte) error {
- println("DECODE")
if len(data) != len(a) {
return io.EOF
}
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index d25ee30a72b..7a05a1bb10e 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -15,26 +15,13 @@ import (
)
const (
- // A generic XML header suitable for use with the output of Marshal and
- // MarshalIndent. This is not automatically added to any output of this
- // package, it is provided as a convenience.
+ // A generic XML header suitable for use with the output of Marshal.
+ // This is not automatically added to any output of this package,
+ // it is provided as a convenience.
Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
)
-// A Marshaler can produce well-formatted XML representing its internal state.
-// It is used by both Marshal and MarshalIndent.
-type Marshaler interface {
- MarshalXML() ([]byte, error)
-}
-
-type printer struct {
- *bufio.Writer
-}
-
-// Marshal writes an XML-formatted representation of v to w.
-//
-// If v implements Marshaler, then Marshal calls its MarshalXML method.
-// Otherwise, Marshal uses the following procedure to create the XML.
+// Marshal returns the XML encoding of v.
//
// Marshal handles an array or slice by marshalling each of the elements.
// Marshal handles a pointer by marshalling the value it points at or, if the
@@ -53,6 +40,7 @@ type printer struct {
// The XML element for a struct contains marshalled elements for each of the
// exported fields of the struct, with these exceptions:
// - the XMLName field, described above, is omitted.
+// - a field with tag "-" is omitted.
// - a field with tag "name,attr" becomes an attribute with
// the given name in the XML element.
// - a field with tag ",attr" becomes an attribute with the
@@ -77,7 +65,7 @@ type printer struct {
// Age int `xml:"person>age"`
// }
//
-// xml.Marshal(w, &Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
+// xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
//
// would be marshalled as:
//
@@ -92,13 +80,38 @@ type printer struct {
// </result>
//
// Marshal will return an error if asked to marshal a channel, function, or map.
-func Marshal(w io.Writer, v interface{}) (err error) {
- p := &printer{bufio.NewWriter(w)}
- err = p.marshalValue(reflect.ValueOf(v), nil)
- p.Flush()
+func Marshal(v interface{}) ([]byte, error) {
+ var b bytes.Buffer
+ if err := NewEncoder(&b).Encode(v); err != nil {
+ return nil, err
+ }
+ return b.Bytes(), nil
+}
+
+// An Encoder writes XML data to an output stream.
+type Encoder struct {
+ printer
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{printer{bufio.NewWriter(w)}}
+}
+
+// Encode writes the XML encoding of v to the stream.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+func (enc *Encoder) Encode(v interface{}) error {
+ err := enc.marshalValue(reflect.ValueOf(v), nil)
+ enc.Flush()
return err
}
+type printer struct {
+ *bufio.Writer
+}
+
func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
if !val.IsValid() {
return nil
@@ -107,18 +120,6 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
kind := val.Kind()
typ := val.Type()
- // Try Marshaler
- if typ.NumMethod() > 0 {
- if marshaler, ok := val.Interface().(Marshaler); ok {
- bytes, err := marshaler.MarshalXML()
- if err != nil {
- return err
- }
- p.Write(bytes)
- return nil
- }
- }
-
// Drill into pointers/interfaces
if kind == reflect.Ptr || kind == reflect.Interface {
if val.IsNil() {
@@ -181,23 +182,43 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
if finfo.flags&fAttr == 0 {
continue
}
- var str string
- if fv := val.FieldByIndex(finfo.idx); fv.Kind() == reflect.String {
- str = fv.String()
- } else {
- str = fmt.Sprint(fv.Interface())
+ fv := val.FieldByIndex(finfo.idx)
+ switch fv.Kind() {
+ case reflect.String, reflect.Array, reflect.Slice:
+ // TODO: Should we really do this once ,omitempty is in?
+ if fv.Len() == 0 {
+ continue
+ }
}
- if str != "" {
- p.WriteByte(' ')
- p.WriteString(finfo.name)
- p.WriteString(`="`)
- Escape(p, []byte(str))
- p.WriteByte('"')
+ p.WriteByte(' ')
+ p.WriteString(finfo.name)
+ p.WriteString(`="`)
+ if err := p.marshalSimple(fv.Type(), fv); err != nil {
+ return err
}
+ p.WriteByte('"')
}
p.WriteByte('>')
- switch k := val.Kind(); k {
+ if val.Kind() == reflect.Struct {
+ err = p.marshalStruct(tinfo, val)
+ } else {
+ err = p.marshalSimple(typ, val)
+ }
+ if err != nil {
+ return err
+ }
+
+ p.WriteByte('<')
+ p.WriteByte('/')
+ p.WriteString(name)
+ p.WriteByte('>')
+
+ return nil
+}
+
+func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
+ switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.WriteString(strconv.FormatInt(val.Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
@@ -205,6 +226,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
case reflect.Float32, reflect.Float64:
p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, 64))
case reflect.String:
+ // TODO: Add EscapeString.
Escape(p, []byte(val.String()))
case reflect.Bool:
p.WriteString(strconv.FormatBool(val.Bool()))
@@ -217,21 +239,10 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
Escape(p, bytes)
case reflect.Slice:
// will be []byte
- bytes := val.Interface().([]byte)
- Escape(p, bytes)
- case reflect.Struct:
- if err := p.marshalStruct(tinfo, val); err != nil {
- return err
- }
+ Escape(p, val.Bytes())
default:
return &UnsupportedTypeError{typ}
}
-
- p.WriteByte('<')
- p.WriteByte('/')
- p.WriteString(name)
- p.WriteByte('>')
-
return nil
}
@@ -358,7 +369,7 @@ func (s *parentStack) push(parents []string) {
s.stack = append(s.stack, parents...)
}
-// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
+// A MarshalXMLError is returned when Marshal encounters a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
Type reflect.Type
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index f23b2cb7e08..e0be3320086 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -5,7 +5,6 @@
package xml
import (
- "bytes"
"reflect"
"strconv"
"strings"
@@ -35,12 +34,6 @@ type Ship struct {
secret string
}
-type RawXML string
-
-func (rx RawXML) MarshalXML() ([]byte, error) {
- return []byte(rx), nil
-}
-
type NamedType string
type Port struct {
@@ -184,6 +177,22 @@ type RecurseB struct {
B string
}
+type PresenceTest struct {
+ Exists *struct{}
+}
+
+type IgnoreTest struct {
+ PublicSecret string `xml:"-"`
+}
+
+type MyBytes []byte
+
+type Data struct {
+ Bytes []byte
+ Attr []byte `xml:",attr"`
+ Custom MyBytes
+}
+
type Plain struct {
V interface{}
}
@@ -225,6 +234,44 @@ var marshalTests = []struct {
{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+ // A pointer to struct{} may be used to test for an element's presence.
+ {
+ Value: &PresenceTest{new(struct{})},
+ ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+ },
+ {
+ Value: &PresenceTest{},
+ ExpectXML: `<PresenceTest></PresenceTest>`,
+ },
+
+ // A pointer to struct{} may be used to test for an element's presence.
+ {
+ Value: &PresenceTest{new(struct{})},
+ ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+ },
+ {
+ Value: &PresenceTest{},
+ ExpectXML: `<PresenceTest></PresenceTest>`,
+ },
+
+ // A []byte field is only nil if the element was not found.
+ {
+ Value: &Data{},
+ ExpectXML: `<Data></Data>`,
+ UnmarshalOnly: true,
+ },
+ {
+ Value: &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},
+ ExpectXML: `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,
+ UnmarshalOnly: true,
+ },
+
+ // Check that []byte works, including named []byte types.
+ {
+ Value: &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},
+ ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,
+ },
+
// Test innerxml
{
Value: &SecretAgent{
@@ -245,13 +292,6 @@ var marshalTests = []struct {
UnmarshalOnly: true,
},
- // Test marshaller interface
- {
- Value: RawXML("</>"),
- ExpectXML: `</>`,
- MarshalOnly: true,
- },
-
// Test structs
{Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
{Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
@@ -542,6 +582,22 @@ var marshalTests = []struct {
},
ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,
},
+
+ // Test ignoring fields via "-" tag
+ {
+ ExpectXML: `<IgnoreTest></IgnoreTest>`,
+ Value: &IgnoreTest{},
+ },
+ {
+ ExpectXML: `<IgnoreTest></IgnoreTest>`,
+ Value: &IgnoreTest{PublicSecret: "can't tell"},
+ MarshalOnly: true,
+ },
+ {
+ ExpectXML: `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,
+ Value: &IgnoreTest{},
+ UnmarshalOnly: true,
+ },
}
func TestMarshal(t *testing.T) {
@@ -549,13 +605,12 @@ func TestMarshal(t *testing.T) {
if test.UnmarshalOnly {
continue
}
- buf := bytes.NewBuffer(nil)
- err := Marshal(buf, test.Value)
+ data, err := Marshal(test.Value)
if err != nil {
t.Errorf("#%d: Error: %s", idx, err)
continue
}
- if got, want := buf.String(), test.ExpectXML; got != want {
+ if got, want := string(data), test.ExpectXML; got != want {
if strings.Contains(want, "\n") {
t.Errorf("#%d: marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", idx, test.Value, got, want)
} else {
@@ -596,8 +651,7 @@ var marshalErrorTests = []struct {
func TestMarshalErrors(t *testing.T) {
for idx, test := range marshalErrorTests {
- buf := bytes.NewBuffer(nil)
- err := Marshal(buf, test.Value)
+ _, err := Marshal(test.Value)
if err == nil || err.Error() != test.Err {
t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
}
@@ -621,8 +675,7 @@ func TestUnmarshal(t *testing.T) {
vt := reflect.TypeOf(test.Value)
dest := reflect.New(vt.Elem()).Interface()
- buffer := bytes.NewBufferString(test.ExpectXML)
- err := Unmarshal(buffer, dest)
+ err := Unmarshal([]byte(test.ExpectXML), dest)
switch fix := dest.(type) {
case *Feed:
@@ -641,17 +694,14 @@ func TestUnmarshal(t *testing.T) {
}
func BenchmarkMarshal(b *testing.B) {
- buf := bytes.NewBuffer(nil)
for i := 0; i < b.N; i++ {
- Marshal(buf, atomValue)
- buf.Truncate(0)
+ Marshal(atomValue)
}
}
func BenchmarkUnmarshal(b *testing.B) {
xml := []byte(atomXml)
for i := 0; i < b.N; i++ {
- buffer := bytes.NewBuffer(xml)
- Unmarshal(buffer, &Feed{})
+ Unmarshal(xml, &Feed{})
}
}
diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go
index 4419ed1e477..871fe059cfa 100644
--- a/libgo/go/encoding/xml/read.go
+++ b/libgo/go/encoding/xml/read.go
@@ -7,7 +7,6 @@ package xml
import (
"bytes"
"errors"
- "io"
"reflect"
"strconv"
"strings"
@@ -20,10 +19,10 @@ import (
// See package json for a textual representation more suitable
// to data structures.
-// Unmarshal parses an XML element from r and uses the
-// reflect library to fill in an arbitrary struct, slice, or string
-// pointed at by val. Well-formed data that does not fit
-// into val is discarded.
+// Unmarshal parses the XML-encoded data and stores the result in
+// the value pointed to by v, which must be an arbitrary struct,
+// slice, or string. Well-formed data that does not fit into v is
+// discarded.
//
// For example, given these definitions:
//
@@ -59,7 +58,7 @@ import (
// <address>123 Main Street</address>
// </result>
//
-// via Unmarshal(r, &result) is equivalent to assigning
+// via Unmarshal(data, &result) is equivalent to assigning
//
// r = Result{
// xml.Name{Local: "result"},
@@ -78,8 +77,9 @@ import (
// field tag.
//
// Because Unmarshal uses the reflect package, it can only assign
-// to exported (upper case) fields. Unmarshal uses a case-insensitive
-// comparison to match XML element names to struct field names.
+// to exported (upper case) fields. Unmarshal uses a case-sensitive
+// comparison to match XML element names to tag values and struct
+// field names.
//
// Unmarshal maps an XML element to a struct using the following rules.
// In the rules, the tag of a field refers to the value associated with the
@@ -132,9 +132,11 @@ import (
// of the above rules and the struct has a field with tag ",any",
// unmarshal maps the sub-element to that struct field.
//
+// * A struct field with tag "-" is never unmarshalled into.
+//
// Unmarshal maps an XML element to a string or []byte by saving the
// concatenation of that element's character data in the string or
-// []byte.
+// []byte. The saved []byte is never nil.
//
// Unmarshal maps an attribute value to a string or []byte by saving
// the value in the string or slice.
@@ -156,18 +158,26 @@ import (
// Unmarshal maps an XML element to a pointer by setting the pointer
// to a freshly allocated value and then mapping the element to that value.
//
-func Unmarshal(r io.Reader, val interface{}) error {
- v := reflect.ValueOf(val)
- if v.Kind() != reflect.Ptr {
+func Unmarshal(data []byte, v interface{}) error {
+ return NewDecoder(bytes.NewBuffer(data)).Decode(v)
+}
+
+// Decode works like xml.Unmarshal, except it reads the decoder
+// stream to find the start element.
+func (d *Decoder) Decode(v interface{}) error {
+ return d.DecodeElement(v, nil)
+}
+
+// DecodeElement works like xml.Unmarshal except that it takes
+// a pointer to the start XML element to decode into v.
+// It is useful when a client reads some raw XML tokens itself
+// but also wants to defer to Unmarshal for some elements.
+func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
+ val := reflect.ValueOf(v)
+ if val.Kind() != reflect.Ptr {
return errors.New("non-pointer passed to Unmarshal")
}
- p := NewParser(r)
- elem := v.Elem()
- err := p.unmarshal(elem, nil)
- if err != nil {
- return err
- }
- return nil
+ return d.unmarshal(val.Elem(), start)
}
// An UnmarshalError represents an error in the unmarshalling process.
@@ -175,22 +185,8 @@ type UnmarshalError string
func (e UnmarshalError) Error() string { return string(e) }
-// The Parser's Unmarshal method is like xml.Unmarshal
-// except that it can be passed a pointer to the initial start element,
-// useful when a client reads some raw XML tokens itself
-// but also defers to Unmarshal for some elements.
-// Passing a nil start element indicates that Unmarshal should
-// read the token stream to find the start element.
-func (p *Parser) Unmarshal(val interface{}, start *StartElement) error {
- v := reflect.ValueOf(val)
- if v.Kind() != reflect.Ptr {
- return errors.New("non-pointer passed to Unmarshal")
- }
- return p.unmarshal(v.Elem(), start)
-}
-
// Unmarshal a single XML element into val.
-func (p *Parser) unmarshal(val reflect.Value, start *StartElement) error {
+func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Find start element if we need it.
if start == nil {
for {
@@ -309,14 +305,12 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) error {
case fAttr:
strv := sv.FieldByIndex(finfo.idx)
// Look for attribute.
- val := ""
for _, a := range start.Attr {
if a.Name.Local == finfo.name {
- val = a.Value
+ copyValue(strv, []byte(a.Value))
break
}
}
- copyValue(strv, []byte(val))
case fCharData:
if !saveData.IsValid() {
@@ -473,7 +467,11 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
case reflect.String:
t.SetString(string(src))
case reflect.Slice:
- t.Set(reflect.ValueOf(src))
+ if len(src) == 0 {
+ // non-nil to flag presence
+ src = []byte{}
+ }
+ t.SetBytes(src)
}
return nil
}
@@ -481,9 +479,9 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
// unmarshalPath walks down an XML structure looking for wanted
// paths, and calls unmarshal on them.
// The consumed result tells whether XML elements have been consumed
-// from the Parser until start's matching end element, or if it's
+// from the Decoder until start's matching end element, or if it's
// still untouched because start is uninteresting for sv's fields.
-func (p *Parser) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
+func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
recurse := false
Loop:
for i := range tinfo.fields {
@@ -547,7 +545,7 @@ Loop:
// Read tokens until we find the end element.
// Token is taking care of making sure the
// end element matches the start element we saw.
-func (p *Parser) Skip() error {
+func (p *Decoder) Skip() error {
for {
tok, err := p.Token()
if err != nil {
diff --git a/libgo/go/encoding/xml/read_test.go b/libgo/go/encoding/xml/read_test.go
index ff61bd7e1c5..833eafc9a58 100644
--- a/libgo/go/encoding/xml/read_test.go
+++ b/libgo/go/encoding/xml/read_test.go
@@ -6,7 +6,6 @@ package xml
import (
"reflect"
- "strings"
"testing"
)
@@ -14,7 +13,7 @@ import (
func TestUnmarshalFeed(t *testing.T) {
var f Feed
- if err := Unmarshal(strings.NewReader(atomFeedString), &f); err != nil {
+ if err := Unmarshal([]byte(atomFeedString), &f); err != nil {
t.Fatalf("Unmarshal: %s", err)
}
if !reflect.DeepEqual(f, atomFeed) {
@@ -281,7 +280,7 @@ var pathTests = []interface{}{
func TestUnmarshalPaths(t *testing.T) {
for _, pt := range pathTests {
v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
- if err := Unmarshal(strings.NewReader(pathTestString), v); err != nil {
+ if err := Unmarshal([]byte(pathTestString), v); err != nil {
t.Fatalf("Unmarshal: %s", err)
}
if !reflect.DeepEqual(v, pt) {
@@ -331,7 +330,7 @@ var badPathTests = []struct {
func TestUnmarshalBadPaths(t *testing.T) {
for _, tt := range badPathTests {
- err := Unmarshal(strings.NewReader(pathTestString), tt.v)
+ err := Unmarshal([]byte(pathTestString), tt.v)
if !reflect.DeepEqual(err, tt.e) {
t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e)
}
@@ -350,7 +349,7 @@ type TestThree struct {
func TestUnmarshalWithoutNameType(t *testing.T) {
var x TestThree
- if err := Unmarshal(strings.NewReader(withoutNameTypeData), &x); err != nil {
+ if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil {
t.Fatalf("Unmarshal: %s", err)
}
if x.Attr != OK {
diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go
index 36b35ed2ee8..2bf2c6b3032 100644
--- a/libgo/go/encoding/xml/typeinfo.go
+++ b/libgo/go/encoding/xml/typeinfo.go
@@ -37,7 +37,6 @@ const (
fAny
// TODO:
- //fIgnore
//fOmitEmpty
fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
@@ -62,7 +61,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
n := typ.NumField()
for i := 0; i < n; i++ {
f := typ.Field(i)
- if f.PkgPath != "" {
+ if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
continue // Private field
}
diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go
index d001c408923..5066f5c0106 100644
--- a/libgo/go/encoding/xml/xml.go
+++ b/libgo/go/encoding/xml/xml.go
@@ -36,7 +36,7 @@ func (e *SyntaxError) Error() string {
// A Name represents an XML name (Local) annotated
// with a name space identifier (Space).
-// In tokens returned by Parser.Token, the Space identifier
+// In tokens returned by Decoder.Token, the Space identifier
// is given as a canonical URL, not the short prefix used
// in the document being parsed.
type Name struct {
@@ -124,9 +124,9 @@ func CopyToken(t Token) Token {
return t
}
-// A Parser represents an XML parser reading a particular input stream.
+// A Decoder represents an XML parser reading a particular input stream.
// The parser assumes that its input is encoded in UTF-8.
-type Parser struct {
+type Decoder struct {
// Strict defaults to true, enforcing the requirements
// of the XML specification.
// If set to false, the parser allows input containing common
@@ -139,9 +139,9 @@ type Parser struct {
//
// Setting:
//
- // p.Strict = false;
- // p.AutoClose = HTMLAutoClose;
- // p.Entity = HTMLEntity
+ // d.Strict = false;
+ // d.AutoClose = HTMLAutoClose;
+ // d.Entity = HTMLEntity
//
// creates a parser that can handle typical HTML.
Strict bool
@@ -184,16 +184,16 @@ type Parser struct {
tmp [32]byte
}
-// NewParser creates a new XML parser reading from r.
-func NewParser(r io.Reader) *Parser {
- p := &Parser{
+// NewDecoder creates a new XML parser reading from r.
+func NewDecoder(r io.Reader) *Decoder {
+ d := &Decoder{
ns: make(map[string]string),
nextByte: -1,
line: 1,
Strict: true,
}
- p.switchToReader(r)
- return p
+ d.switchToReader(r)
+ return d
}
// Token returns the next XML token in the input stream.
@@ -218,17 +218,17 @@ func NewParser(r io.Reader) *Parser {
// set to the URL identifying its name space when known.
// If Token encounters an unrecognized name space prefix,
// it uses the prefix as the Space rather than report an error.
-func (p *Parser) Token() (t Token, err error) {
- if p.nextToken != nil {
- t = p.nextToken
- p.nextToken = nil
- } else if t, err = p.RawToken(); err != nil {
+func (d *Decoder) Token() (t Token, err error) {
+ if d.nextToken != nil {
+ t = d.nextToken
+ d.nextToken = nil
+ } else if t, err = d.RawToken(); err != nil {
return
}
- if !p.Strict {
- if t1, ok := p.autoClose(t); ok {
- p.nextToken = t
+ if !d.Strict {
+ if t1, ok := d.autoClose(t); ok {
+ d.nextToken = t
t = t1
}
}
@@ -240,29 +240,29 @@ func (p *Parser) Token() (t Token, err error) {
// the translations first.
for _, a := range t1.Attr {
if a.Name.Space == "xmlns" {
- v, ok := p.ns[a.Name.Local]
- p.pushNs(a.Name.Local, v, ok)
- p.ns[a.Name.Local] = a.Value
+ v, ok := d.ns[a.Name.Local]
+ d.pushNs(a.Name.Local, v, ok)
+ d.ns[a.Name.Local] = a.Value
}
if a.Name.Space == "" && a.Name.Local == "xmlns" {
// Default space for untagged names
- v, ok := p.ns[""]
- p.pushNs("", v, ok)
- p.ns[""] = a.Value
+ v, ok := d.ns[""]
+ d.pushNs("", v, ok)
+ d.ns[""] = a.Value
}
}
- p.translate(&t1.Name, true)
+ d.translate(&t1.Name, true)
for i := range t1.Attr {
- p.translate(&t1.Attr[i].Name, false)
+ d.translate(&t1.Attr[i].Name, false)
}
- p.pushElement(t1.Name)
+ d.pushElement(t1.Name)
t = t1
case EndElement:
- p.translate(&t1.Name, true)
- if !p.popElement(&t1) {
- return nil, p.err
+ d.translate(&t1.Name, true)
+ if !d.popElement(&t1) {
+ return nil, d.err
}
t = t1
}
@@ -272,7 +272,7 @@ func (p *Parser) Token() (t Token, err error) {
// Apply name space translation to name n.
// The default name space (for Space=="")
// applies only to element names, not to attribute names.
-func (p *Parser) translate(n *Name, isElementName bool) {
+func (d *Decoder) translate(n *Name, isElementName bool) {
switch {
case n.Space == "xmlns":
return
@@ -281,20 +281,20 @@ func (p *Parser) translate(n *Name, isElementName bool) {
case n.Space == "" && n.Local == "xmlns":
return
}
- if v, ok := p.ns[n.Space]; ok {
+ if v, ok := d.ns[n.Space]; ok {
n.Space = v
}
}
-func (p *Parser) switchToReader(r io.Reader) {
+func (d *Decoder) switchToReader(r io.Reader) {
// Get efficient byte at a time reader.
// Assume that if reader has its own
// ReadByte, it's efficient enough.
// Otherwise, use bufio.
if rb, ok := r.(io.ByteReader); ok {
- p.r = rb
+ d.r = rb
} else {
- p.r = bufio.NewReader(r)
+ d.r = bufio.NewReader(r)
}
}
@@ -314,47 +314,47 @@ const (
stkNs
)
-func (p *Parser) push(kind int) *stack {
- s := p.free
+func (d *Decoder) push(kind int) *stack {
+ s := d.free
if s != nil {
- p.free = s.next
+ d.free = s.next
} else {
s = new(stack)
}
- s.next = p.stk
+ s.next = d.stk
s.kind = kind
- p.stk = s
+ d.stk = s
return s
}
-func (p *Parser) pop() *stack {
- s := p.stk
+func (d *Decoder) pop() *stack {
+ s := d.stk
if s != nil {
- p.stk = s.next
- s.next = p.free
- p.free = s
+ d.stk = s.next
+ s.next = d.free
+ d.free = s
}
return s
}
// Record that we are starting an element with the given name.
-func (p *Parser) pushElement(name Name) {
- s := p.push(stkStart)
+func (d *Decoder) pushElement(name Name) {
+ s := d.push(stkStart)
s.name = name
}
// Record that we are changing the value of ns[local].
// The old value is url, ok.
-func (p *Parser) pushNs(local string, url string, ok bool) {
- s := p.push(stkNs)
+func (d *Decoder) pushNs(local string, url string, ok bool) {
+ s := d.push(stkNs)
s.name.Local = local
s.name.Space = url
s.ok = ok
}
// Creates a SyntaxError with the current line number.
-func (p *Parser) syntaxError(msg string) error {
- return &SyntaxError{Msg: msg, Line: p.line}
+func (d *Decoder) syntaxError(msg string) error {
+ return &SyntaxError{Msg: msg, Line: d.line}
}
// Record that we are ending an element with the given name.
@@ -363,36 +363,36 @@ func (p *Parser) syntaxError(msg string) error {
// After popping the element, apply any undo records from
// the stack to restore the name translations that existed
// before we saw this element.
-func (p *Parser) popElement(t *EndElement) bool {
- s := p.pop()
+func (d *Decoder) popElement(t *EndElement) bool {
+ s := d.pop()
name := t.Name
switch {
case s == nil || s.kind != stkStart:
- p.err = p.syntaxError("unexpected end element </" + name.Local + ">")
+ d.err = d.syntaxError("unexpected end element </" + name.Local + ">")
return false
case s.name.Local != name.Local:
- if !p.Strict {
- p.needClose = true
- p.toClose = t.Name
+ if !d.Strict {
+ d.needClose = true
+ d.toClose = t.Name
t.Name = s.name
return true
}
- p.err = p.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
+ d.err = d.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
return false
case s.name.Space != name.Space:
- p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
+ d.err = d.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
"closed by </" + name.Local + "> in space " + name.Space)
return false
}
// Pop stack until a Start is on the top, undoing the
// translations that were associated with the element we just closed.
- for p.stk != nil && p.stk.kind != stkStart {
- s := p.pop()
+ for d.stk != nil && d.stk.kind != stkStart {
+ s := d.pop()
if s.ok {
- p.ns[s.name.Local] = s.name.Space
+ d.ns[s.name.Local] = s.name.Space
} else {
- delete(p.ns, s.name.Local)
+ delete(d.ns, s.name.Local)
}
}
@@ -401,17 +401,17 @@ func (p *Parser) popElement(t *EndElement) bool {
// If the top element on the stack is autoclosing and
// t is not the end tag, invent the end tag.
-func (p *Parser) autoClose(t Token) (Token, bool) {
- if p.stk == nil || p.stk.kind != stkStart {
+func (d *Decoder) autoClose(t Token) (Token, bool) {
+ if d.stk == nil || d.stk.kind != stkStart {
return nil, false
}
- name := strings.ToLower(p.stk.name.Local)
- for _, s := range p.AutoClose {
+ name := strings.ToLower(d.stk.name.Local)
+ for _, s := range d.AutoClose {
if strings.ToLower(s) == name {
// This one should be auto closed if t doesn't close it.
et, ok := t.(EndElement)
if !ok || et.Name.Local != name {
- return EndElement{p.stk.name}, true
+ return EndElement{d.stk.name}, true
}
break
}
@@ -422,53 +422,53 @@ func (p *Parser) autoClose(t Token) (Token, bool) {
// RawToken is like Token but does not verify that
// start and end elements match and does not translate
// name space prefixes to their corresponding URLs.
-func (p *Parser) RawToken() (Token, error) {
- if p.err != nil {
- return nil, p.err
+func (d *Decoder) RawToken() (Token, error) {
+ if d.err != nil {
+ return nil, d.err
}
- if p.needClose {
+ if d.needClose {
// The last element we read was self-closing and
// we returned just the StartElement half.
// Return the EndElement half now.
- p.needClose = false
- return EndElement{p.toClose}, nil
+ d.needClose = false
+ return EndElement{d.toClose}, nil
}
- b, ok := p.getc()
+ b, ok := d.getc()
if !ok {
- return nil, p.err
+ return nil, d.err
}
if b != '<' {
// Text section.
- p.ungetc(b)
- data := p.text(-1, false)
+ d.ungetc(b)
+ data := d.text(-1, false)
if data == nil {
- return nil, p.err
+ return nil, d.err
}
return CharData(data), nil
}
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
switch b {
case '/':
// </: End element
var name Name
- if name, ok = p.nsname(); !ok {
- if p.err == nil {
- p.err = p.syntaxError("expected element name after </")
+ if name, ok = d.nsname(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected element name after </")
}
- return nil, p.err
+ return nil, d.err
}
- p.space()
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ d.space()
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if b != '>' {
- p.err = p.syntaxError("invalid characters between </" + name.Local + " and >")
- return nil, p.err
+ d.err = d.syntaxError("invalid characters between </" + name.Local + " and >")
+ return nil, d.err
}
return EndElement{name}, nil
@@ -477,95 +477,95 @@ func (p *Parser) RawToken() (Token, error) {
// TODO(rsc): Should parse the <?xml declaration to make sure
// the version is 1.0 and the encoding is UTF-8.
var target string
- if target, ok = p.name(); !ok {
- if p.err == nil {
- p.err = p.syntaxError("expected target name after <?")
+ if target, ok = d.name(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected target name after <?")
}
- return nil, p.err
+ return nil, d.err
}
- p.space()
- p.buf.Reset()
+ d.space()
+ d.buf.Reset()
var b0 byte
for {
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
- p.buf.WriteByte(b)
+ d.buf.WriteByte(b)
if b0 == '?' && b == '>' {
break
}
b0 = b
}
- data := p.buf.Bytes()
+ data := d.buf.Bytes()
data = data[0 : len(data)-2] // chop ?>
if target == "xml" {
enc := procInstEncoding(string(data))
if enc != "" && enc != "utf-8" && enc != "UTF-8" {
- if p.CharsetReader == nil {
- p.err = fmt.Errorf("xml: encoding %q declared but Parser.CharsetReader is nil", enc)
- return nil, p.err
+ if d.CharsetReader == nil {
+ d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
+ return nil, d.err
}
- newr, err := p.CharsetReader(enc, p.r.(io.Reader))
+ newr, err := d.CharsetReader(enc, d.r.(io.Reader))
if err != nil {
- p.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
- return nil, p.err
+ d.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
+ return nil, d.err
}
if newr == nil {
panic("CharsetReader returned a nil Reader for charset " + enc)
}
- p.switchToReader(newr)
+ d.switchToReader(newr)
}
}
return ProcInst{target, data}, nil
case '!':
// <!: Maybe comment, maybe CDATA.
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
switch b {
case '-': // <!-
// Probably <!-- for a comment.
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if b != '-' {
- p.err = p.syntaxError("invalid sequence <!- not part of <!--")
- return nil, p.err
+ d.err = d.syntaxError("invalid sequence <!- not part of <!--")
+ return nil, d.err
}
// Look for terminator.
- p.buf.Reset()
+ d.buf.Reset()
var b0, b1 byte
for {
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
- p.buf.WriteByte(b)
+ d.buf.WriteByte(b)
if b0 == '-' && b1 == '-' && b == '>' {
break
}
b0, b1 = b1, b
}
- data := p.buf.Bytes()
+ data := d.buf.Bytes()
data = data[0 : len(data)-3] // chop -->
return Comment(data), nil
case '[': // <![
// Probably <![CDATA[.
for i := 0; i < 6; i++ {
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if b != "CDATA["[i] {
- p.err = p.syntaxError("invalid <![ sequence")
- return nil, p.err
+ d.err = d.syntaxError("invalid <![ sequence")
+ return nil, d.err
}
}
// Have <![CDATA[. Read text until ]]>.
- data := p.text(-1, true)
+ data := d.text(-1, true)
if data == nil {
- return nil, p.err
+ return nil, d.err
}
return CharData(data), nil
}
@@ -573,18 +573,18 @@ func (p *Parser) RawToken() (Token, error) {
// Probably a directive: <!DOCTYPE ...>, <!ENTITY ...>, etc.
// We don't care, but accumulate for caller. Quoted angle
// brackets do not count for nesting.
- p.buf.Reset()
- p.buf.WriteByte(b)
+ d.buf.Reset()
+ d.buf.WriteByte(b)
inquote := uint8(0)
depth := 0
for {
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if inquote == 0 && b == '>' && depth == 0 {
break
}
- p.buf.WriteByte(b)
+ d.buf.WriteByte(b)
switch {
case b == inquote:
inquote = 0
@@ -602,45 +602,45 @@ func (p *Parser) RawToken() (Token, error) {
depth++
}
}
- return Directive(p.buf.Bytes()), nil
+ return Directive(d.buf.Bytes()), nil
}
// Must be an open element like <a href="foo">
- p.ungetc(b)
+ d.ungetc(b)
var (
name Name
empty bool
attr []Attr
)
- if name, ok = p.nsname(); !ok {
- if p.err == nil {
- p.err = p.syntaxError("expected element name after <")
+ if name, ok = d.nsname(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected element name after <")
}
- return nil, p.err
+ return nil, d.err
}
attr = make([]Attr, 0, 4)
for {
- p.space()
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ d.space()
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if b == '/' {
empty = true
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if b != '>' {
- p.err = p.syntaxError("expected /> in element")
- return nil, p.err
+ d.err = d.syntaxError("expected /> in element")
+ return nil, d.err
}
break
}
if b == '>' {
break
}
- p.ungetc(b)
+ d.ungetc(b)
n := len(attr)
if n >= cap(attr) {
@@ -650,85 +650,85 @@ func (p *Parser) RawToken() (Token, error) {
}
attr = attr[0 : n+1]
a := &attr[n]
- if a.Name, ok = p.nsname(); !ok {
- if p.err == nil {
- p.err = p.syntaxError("expected attribute name in element")
+ if a.Name, ok = d.nsname(); !ok {
+ if d.err == nil {
+ d.err = d.syntaxError("expected attribute name in element")
}
- return nil, p.err
+ return nil, d.err
}
- p.space()
- if b, ok = p.mustgetc(); !ok {
- return nil, p.err
+ d.space()
+ if b, ok = d.mustgetc(); !ok {
+ return nil, d.err
}
if b != '=' {
- if p.Strict {
- p.err = p.syntaxError("attribute name without = in element")
- return nil, p.err
+ if d.Strict {
+ d.err = d.syntaxError("attribute name without = in element")
+ return nil, d.err
} else {
- p.ungetc(b)
+ d.ungetc(b)
a.Value = a.Name.Local
}
} else {
- p.space()
- data := p.attrval()
+ d.space()
+ data := d.attrval()
if data == nil {
- return nil, p.err
+ return nil, d.err
}
a.Value = string(data)
}
}
if empty {
- p.needClose = true
- p.toClose = name
+ d.needClose = true
+ d.toClose = name
}
return StartElement{name, attr}, nil
}
-func (p *Parser) attrval() []byte {
- b, ok := p.mustgetc()
+func (d *Decoder) attrval() []byte {
+ b, ok := d.mustgetc()
if !ok {
return nil
}
// Handle quoted attribute values
if b == '"' || b == '\'' {
- return p.text(int(b), false)
+ return d.text(int(b), false)
}
// Handle unquoted attribute values for strict parsers
- if p.Strict {
- p.err = p.syntaxError("unquoted or missing attribute value in element")
+ if d.Strict {
+ d.err = d.syntaxError("unquoted or missing attribute value in element")
return nil
}
// Handle unquoted attribute values for unstrict parsers
- p.ungetc(b)
- p.buf.Reset()
+ d.ungetc(b)
+ d.buf.Reset()
for {
- b, ok = p.mustgetc()
+ b, ok = d.mustgetc()
if !ok {
return nil
}
// http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
'0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
- p.buf.WriteByte(b)
+ d.buf.WriteByte(b)
} else {
- p.ungetc(b)
+ d.ungetc(b)
break
}
}
- return p.buf.Bytes()
+ return d.buf.Bytes()
}
// Skip spaces if any
-func (p *Parser) space() {
+func (d *Decoder) space() {
for {
- b, ok := p.getc()
+ b, ok := d.getc()
if !ok {
return
}
switch b {
case ' ', '\r', '\n', '\t':
default:
- p.ungetc(b)
+ d.ungetc(b)
return
}
}
@@ -736,35 +736,35 @@ func (p *Parser) space() {
// Read a single byte.
// If there is no byte to read, return ok==false
-// and leave the error in p.err.
+// and leave the error in d.err.
// Maintain line number.
-func (p *Parser) getc() (b byte, ok bool) {
- if p.err != nil {
+func (d *Decoder) getc() (b byte, ok bool) {
+ if d.err != nil {
return 0, false
}
- if p.nextByte >= 0 {
- b = byte(p.nextByte)
- p.nextByte = -1
+ if d.nextByte >= 0 {
+ b = byte(d.nextByte)
+ d.nextByte = -1
} else {
- b, p.err = p.r.ReadByte()
- if p.err != nil {
+ b, d.err = d.r.ReadByte()
+ if d.err != nil {
return 0, false
}
- if p.saved != nil {
- p.saved.WriteByte(b)
+ if d.saved != nil {
+ d.saved.WriteByte(b)
}
}
if b == '\n' {
- p.line++
+ d.line++
}
return b, true
}
// Return saved offset.
// If we did ungetc (nextByte >= 0), have to back up one.
-func (p *Parser) savedOffset() int {
- n := p.saved.Len()
- if p.nextByte >= 0 {
+func (d *Decoder) savedOffset() int {
+ n := d.saved.Len()
+ if d.nextByte >= 0 {
n--
}
return n
@@ -772,23 +772,23 @@ func (p *Parser) savedOffset() int {
// Must read a single byte.
// If there is no byte to read,
-// set p.err to SyntaxError("unexpected EOF")
+// set d.err to SyntaxError("unexpected EOF")
// and return ok==false
-func (p *Parser) mustgetc() (b byte, ok bool) {
- if b, ok = p.getc(); !ok {
- if p.err == io.EOF {
- p.err = p.syntaxError("unexpected EOF")
+func (d *Decoder) mustgetc() (b byte, ok bool) {
+ if b, ok = d.getc(); !ok {
+ if d.err == io.EOF {
+ d.err = d.syntaxError("unexpected EOF")
}
}
return
}
// Unread a single byte.
-func (p *Parser) ungetc(b byte) {
+func (d *Decoder) ungetc(b byte) {
if b == '\n' {
- p.line--
+ d.line--
}
- p.nextByte = int(b)
+ d.nextByte = int(b)
}
var entity = map[string]int{
@@ -802,18 +802,18 @@ var entity = map[string]int{
// Read plain text section (XML calls it character data).
// If quote >= 0, we are in a quoted string and need to find the matching quote.
// If cdata == true, we are in a <![CDATA[ section and need to find ]]>.
-// On failure return nil and leave the error in p.err.
-func (p *Parser) text(quote int, cdata bool) []byte {
+// On failure return nil and leave the error in d.err.
+func (d *Decoder) text(quote int, cdata bool) []byte {
var b0, b1 byte
var trunc int
- p.buf.Reset()
+ d.buf.Reset()
Input:
for {
- b, ok := p.getc()
+ b, ok := d.getc()
if !ok {
if cdata {
- if p.err == io.EOF {
- p.err = p.syntaxError("unexpected EOF in CDATA section")
+ if d.err == io.EOF {
+ d.err = d.syntaxError("unexpected EOF in CDATA section")
}
return nil
}
@@ -827,17 +827,17 @@ Input:
trunc = 2
break Input
}
- p.err = p.syntaxError("unescaped ]]> not in CDATA section")
+ d.err = d.syntaxError("unescaped ]]> not in CDATA section")
return nil
}
// Stop reading text if we see a <.
if b == '<' && !cdata {
if quote >= 0 {
- p.err = p.syntaxError("unescaped < inside quoted string")
+ d.err = d.syntaxError("unescaped < inside quoted string")
return nil
}
- p.ungetc('<')
+ d.ungetc('<')
break Input
}
if quote >= 0 && b == byte(quote) {
@@ -850,16 +850,16 @@ Input:
// Parsers are required to recognize lt, gt, amp, apos, and quot
// even if they have not been declared. That's all we allow.
var i int
- for i = 0; i < len(p.tmp); i++ {
+ for i = 0; i < len(d.tmp); i++ {
var ok bool
- p.tmp[i], ok = p.getc()
+ d.tmp[i], ok = d.getc()
if !ok {
- if p.err == io.EOF {
- p.err = p.syntaxError("unexpected EOF")
+ if d.err == io.EOF {
+ d.err = d.syntaxError("unexpected EOF")
}
return nil
}
- c := p.tmp[i]
+ c := d.tmp[i]
if c == ';' {
break
}
@@ -869,18 +869,18 @@ Input:
c == '_' || c == '#' {
continue
}
- p.ungetc(c)
+ d.ungetc(c)
break
}
- s := string(p.tmp[0:i])
- if i >= len(p.tmp) {
- if !p.Strict {
+ s := string(d.tmp[0:i])
+ if i >= len(d.tmp) {
+ if !d.Strict {
b0, b1 = 0, 0
- p.buf.WriteByte('&')
- p.buf.Write(p.tmp[0:i])
+ d.buf.WriteByte('&')
+ d.buf.Write(d.tmp[0:i])
continue Input
}
- p.err = p.syntaxError("character entity expression &" + s + "... too long")
+ d.err = d.syntaxError("character entity expression &" + s + "... too long")
return nil
}
var haveText bool
@@ -901,28 +901,28 @@ Input:
if r, ok := entity[s]; ok {
text = string(r)
haveText = true
- } else if p.Entity != nil {
- text, haveText = p.Entity[s]
+ } else if d.Entity != nil {
+ text, haveText = d.Entity[s]
}
}
if !haveText {
- if !p.Strict {
+ if !d.Strict {
b0, b1 = 0, 0
- p.buf.WriteByte('&')
- p.buf.Write(p.tmp[0:i])
+ d.buf.WriteByte('&')
+ d.buf.Write(d.tmp[0:i])
continue Input
}
- p.err = p.syntaxError("invalid character entity &" + s + ";")
+ d.err = d.syntaxError("invalid character entity &" + s + ";")
return nil
}
- p.buf.Write([]byte(text))
+ d.buf.Write([]byte(text))
b0, b1 = 0, 0
continue Input
}
- p.buf.WriteByte(b)
+ d.buf.WriteByte(b)
b0, b1 = b1, b
}
- data := p.buf.Bytes()
+ data := d.buf.Bytes()
data = data[0 : len(data)-trunc]
// Inspect each rune for being a disallowed character.
@@ -930,12 +930,12 @@ Input:
for len(buf) > 0 {
r, size := utf8.DecodeRune(buf)
if r == utf8.RuneError && size == 1 {
- p.err = p.syntaxError("invalid UTF-8")
+ d.err = d.syntaxError("invalid UTF-8")
return nil
}
buf = buf[size:]
if !isInCharacterRange(r) {
- p.err = p.syntaxError(fmt.Sprintf("illegal character code %U", r))
+ d.err = d.syntaxError(fmt.Sprintf("illegal character code %U", r))
return nil
}
}
@@ -970,8 +970,8 @@ func isInCharacterRange(r rune) (inrange bool) {
// Get name space name: name with a : stuck in the middle.
// The part before the : is the name space identifier.
-func (p *Parser) nsname() (name Name, ok bool) {
- s, ok := p.name()
+func (d *Decoder) nsname() (name Name, ok bool) {
+ s, ok := d.name()
if !ok {
return
}
@@ -986,37 +986,37 @@ func (p *Parser) nsname() (name Name, ok bool) {
}
// Get name: /first(first|second)*/
-// Do not set p.err if the name is missing (unless unexpected EOF is received):
+// Do not set d.err if the name is missing (unless unexpected EOF is received):
// let the caller provide better context.
-func (p *Parser) name() (s string, ok bool) {
+func (d *Decoder) name() (s string, ok bool) {
var b byte
- if b, ok = p.mustgetc(); !ok {
+ if b, ok = d.mustgetc(); !ok {
return
}
// As a first approximation, we gather the bytes [A-Za-z_:.-\x80-\xFF]*
if b < utf8.RuneSelf && !isNameByte(b) {
- p.ungetc(b)
+ d.ungetc(b)
return "", false
}
- p.buf.Reset()
- p.buf.WriteByte(b)
+ d.buf.Reset()
+ d.buf.WriteByte(b)
for {
- if b, ok = p.mustgetc(); !ok {
+ if b, ok = d.mustgetc(); !ok {
return
}
if b < utf8.RuneSelf && !isNameByte(b) {
- p.ungetc(b)
+ d.ungetc(b)
break
}
- p.buf.WriteByte(b)
+ d.buf.WriteByte(b)
}
// Then we check the characters.
- s = p.buf.String()
+ s = d.buf.String()
for i, c := range s {
if !unicode.Is(first, c) && (i == 0 || !unicode.Is(second, c)) {
- p.err = p.syntaxError("invalid XML name: " + s)
+ d.err = d.syntaxError("invalid XML name: " + s)
return "", false
}
}
diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go
index 524d4dda4f4..1d0696ce087 100644
--- a/libgo/go/encoding/xml/xml_test.go
+++ b/libgo/go/encoding/xml/xml_test.go
@@ -5,7 +5,6 @@
package xml
import (
- "bytes"
"io"
"reflect"
"strings"
@@ -155,8 +154,8 @@ var xmlInput = []string{
}
func TestRawToken(t *testing.T) {
- p := NewParser(strings.NewReader(testInput))
- testRawToken(t, p, rawTokens)
+ d := NewDecoder(strings.NewReader(testInput))
+ testRawToken(t, d, rawTokens)
}
type downCaser struct {
@@ -179,27 +178,27 @@ func (d *downCaser) Read(p []byte) (int, error) {
func TestRawTokenAltEncoding(t *testing.T) {
sawEncoding := ""
- p := NewParser(strings.NewReader(testInputAltEncoding))
- p.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+ d := NewDecoder(strings.NewReader(testInputAltEncoding))
+ d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
sawEncoding = charset
if charset != "x-testing-uppercase" {
t.Fatalf("unexpected charset %q", charset)
}
return &downCaser{t, input.(io.ByteReader)}, nil
}
- testRawToken(t, p, rawTokensAltEncoding)
+ testRawToken(t, d, rawTokensAltEncoding)
}
func TestRawTokenAltEncodingNoConverter(t *testing.T) {
- p := NewParser(strings.NewReader(testInputAltEncoding))
- token, err := p.RawToken()
+ d := NewDecoder(strings.NewReader(testInputAltEncoding))
+ token, err := d.RawToken()
if token == nil {
t.Fatalf("expected a token on first RawToken call")
}
if err != nil {
t.Fatal(err)
}
- token, err = p.RawToken()
+ token, err = d.RawToken()
if token != nil {
t.Errorf("expected a nil token; got %#v", token)
}
@@ -213,9 +212,9 @@ func TestRawTokenAltEncodingNoConverter(t *testing.T) {
}
}
-func testRawToken(t *testing.T, p *Parser, rawTokens []Token) {
+func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
for i, want := range rawTokens {
- have, err := p.RawToken()
+ have, err := d.RawToken()
if err != nil {
t.Fatalf("token %d: unexpected error: %s", i, err)
}
@@ -258,10 +257,10 @@ var nestedDirectivesTokens = []Token{
}
func TestNestedDirectives(t *testing.T) {
- p := NewParser(strings.NewReader(nestedDirectivesInput))
+ d := NewDecoder(strings.NewReader(nestedDirectivesInput))
for i, want := range nestedDirectivesTokens {
- have, err := p.Token()
+ have, err := d.Token()
if err != nil {
t.Fatalf("token %d: unexpected error: %s", i, err)
}
@@ -272,10 +271,10 @@ func TestNestedDirectives(t *testing.T) {
}
func TestToken(t *testing.T) {
- p := NewParser(strings.NewReader(testInput))
+ d := NewDecoder(strings.NewReader(testInput))
for i, want := range cookedTokens {
- have, err := p.Token()
+ have, err := d.Token()
if err != nil {
t.Fatalf("token %d: unexpected error: %s", i, err)
}
@@ -287,9 +286,9 @@ func TestToken(t *testing.T) {
func TestSyntax(t *testing.T) {
for i := range xmlInput {
- p := NewParser(strings.NewReader(xmlInput[i]))
+ d := NewDecoder(strings.NewReader(xmlInput[i]))
var err error
- for _, err = p.Token(); err == nil; _, err = p.Token() {
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
}
if _, ok := err.(*SyntaxError); !ok {
t.Fatalf(`xmlInput "%s": expected SyntaxError not received`, xmlInput[i])
@@ -368,8 +367,7 @@ const testScalarsInput = `<allscalars>
func TestAllScalars(t *testing.T) {
var a allScalars
- buf := bytes.NewBufferString(testScalarsInput)
- err := Unmarshal(buf, &a)
+ err := Unmarshal([]byte(testScalarsInput), &a)
if err != nil {
t.Fatal(err)
@@ -386,8 +384,7 @@ type item struct {
func TestIssue569(t *testing.T) {
data := `<item><Field_a>abcd</Field_a></item>`
var i item
- buf := bytes.NewBufferString(data)
- err := Unmarshal(buf, &i)
+ err := Unmarshal([]byte(data), &i)
if err != nil || i.Field_a != "abcd" {
t.Fatal("Expecting abcd")
@@ -396,9 +393,9 @@ func TestIssue569(t *testing.T) {
func TestUnquotedAttrs(t *testing.T) {
data := "<tag attr=azAZ09:-_\t>"
- p := NewParser(strings.NewReader(data))
- p.Strict = false
- token, err := p.Token()
+ d := NewDecoder(strings.NewReader(data))
+ d.Strict = false
+ token, err := d.Token()
if _, ok := err.(*SyntaxError); ok {
t.Errorf("Unexpected error: %v", err)
}
@@ -422,9 +419,9 @@ func TestValuelessAttrs(t *testing.T) {
{"<input checked />", "input", "checked"},
}
for _, test := range tests {
- p := NewParser(strings.NewReader(test[0]))
- p.Strict = false
- token, err := p.Token()
+ d := NewDecoder(strings.NewReader(test[0]))
+ d.Strict = false
+ token, err := d.Token()
if _, ok := err.(*SyntaxError); ok {
t.Errorf("Unexpected error: %v", err)
}
@@ -472,9 +469,9 @@ func TestCopyTokenStartElement(t *testing.T) {
func TestSyntaxErrorLineNum(t *testing.T) {
testInput := "<P>Foo<P>\n\n<P>Bar</>\n"
- p := NewParser(strings.NewReader(testInput))
+ d := NewDecoder(strings.NewReader(testInput))
var err error
- for _, err = p.Token(); err == nil; _, err = p.Token() {
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
}
synerr, ok := err.(*SyntaxError)
if !ok {
@@ -487,41 +484,41 @@ func TestSyntaxErrorLineNum(t *testing.T) {
func TestTrailingRawToken(t *testing.T) {
input := `<FOO></FOO> `
- p := NewParser(strings.NewReader(input))
+ d := NewDecoder(strings.NewReader(input))
var err error
- for _, err = p.RawToken(); err == nil; _, err = p.RawToken() {
+ for _, err = d.RawToken(); err == nil; _, err = d.RawToken() {
}
if err != io.EOF {
- t.Fatalf("p.RawToken() = _, %v, want _, io.EOF", err)
+ t.Fatalf("d.RawToken() = _, %v, want _, io.EOF", err)
}
}
func TestTrailingToken(t *testing.T) {
input := `<FOO></FOO> `
- p := NewParser(strings.NewReader(input))
+ d := NewDecoder(strings.NewReader(input))
var err error
- for _, err = p.Token(); err == nil; _, err = p.Token() {
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
}
if err != io.EOF {
- t.Fatalf("p.Token() = _, %v, want _, io.EOF", err)
+ t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
}
}
func TestEntityInsideCDATA(t *testing.T) {
input := `<test><![CDATA[ &val=foo ]]></test>`
- p := NewParser(strings.NewReader(input))
+ d := NewDecoder(strings.NewReader(input))
var err error
- for _, err = p.Token(); err == nil; _, err = p.Token() {
+ for _, err = d.Token(); err == nil; _, err = d.Token() {
}
if err != io.EOF {
- t.Fatalf("p.Token() = _, %v, want _, io.EOF", err)
+ t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
}
}
// The last three tests (respectively one for characters in attribute
// names and two for character entities) pass not because of code
// changed for issue 1259, but instead pass with the given messages
-// from other parts of xml.Parser. I provide these to note the
+// from other parts of xml.Decoder. I provide these to note the
// current behavior of situations where one might think that character
// range checking would detect the error, but it does not in fact.
@@ -541,15 +538,15 @@ var characterTests = []struct {
func TestDisallowedCharacters(t *testing.T) {
for i, tt := range characterTests {
- p := NewParser(strings.NewReader(tt.in))
+ d := NewDecoder(strings.NewReader(tt.in))
var err error
for err == nil {
- _, err = p.Token()
+ _, err = d.Token()
}
synerr, ok := err.(*SyntaxError)
if !ok {
- t.Fatalf("input %d p.Token() = _, %v, want _, *SyntaxError", i, err)
+ t.Fatalf("input %d d.Token() = _, %v, want _, *SyntaxError", i, err)
}
if synerr.Msg != tt.err {
t.Fatalf("input %d synerr.Msg wrong: want '%s', got '%s'", i, tt.err, synerr.Msg)
diff --git a/libgo/go/exp/ebnflint/ebnflint.go b/libgo/go/exp/ebnflint/ebnflint.go
index 6d6f516c905..2cb5aa6ed6c 100644
--- a/libgo/go/exp/ebnflint/ebnflint.go
+++ b/libgo/go/exp/ebnflint/ebnflint.go
@@ -11,6 +11,7 @@ import (
"fmt"
"go/scanner"
"go/token"
+ "io"
"io/ioutil"
"os"
"path/filepath"
@@ -76,34 +77,46 @@ func main() {
flag.Parse()
var (
- filename string
- src []byte
- err error
+ name string
+ r io.Reader
)
switch flag.NArg() {
case 0:
- filename = "<stdin>"
- src, err = ioutil.ReadAll(os.Stdin)
+ name, r = "<stdin>", os.Stdin
case 1:
- filename = flag.Arg(0)
- src, err = ioutil.ReadFile(filename)
+ name = flag.Arg(0)
default:
usage()
}
- if err != nil {
+
+ if err := verify(name, *start, r); err != nil {
report(err)
}
+}
- if filepath.Ext(filename) == ".html" || bytes.Index(src, open) >= 0 {
- src = extractEBNF(src)
+func verify(name, start string, r io.Reader) error {
+ if r == nil {
+ f, err := os.Open(name)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ r = f
}
- grammar, err := ebnf.Parse(filename, bytes.NewBuffer(src))
+ src, err := ioutil.ReadAll(r)
if err != nil {
- report(err)
+ return err
}
- if err = ebnf.Verify(grammar, *start); err != nil {
- report(err)
+ if filepath.Ext(name) == ".html" || bytes.Index(src, open) >= 0 {
+ src = extractEBNF(src)
+ }
+
+ grammar, err := ebnf.Parse(name, bytes.NewBuffer(src))
+ if err != nil {
+ return err
}
+
+ return ebnf.Verify(grammar, start)
}
diff --git a/libgo/go/exp/ebnflint/ebnflint_test.go b/libgo/go/exp/ebnflint/ebnflint_test.go
new file mode 100644
index 00000000000..875dbc19aca
--- /dev/null
+++ b/libgo/go/exp/ebnflint/ebnflint_test.go
@@ -0,0 +1,16 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+ "testing"
+)
+
+func TestSpec(t *testing.T) {
+ if err := verify(runtime.GOROOT()+"/doc/go_spec.html", "SourceFile", nil); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/libgo/go/html/const.go b/libgo/go/exp/html/const.go
index d7cc8bb9a99..d7cc8bb9a99 100644
--- a/libgo/go/html/const.go
+++ b/libgo/go/exp/html/const.go
diff --git a/libgo/go/html/doc.go b/libgo/go/exp/html/doc.go
index 56b194ffb90..56b194ffb90 100644
--- a/libgo/go/html/doc.go
+++ b/libgo/go/exp/html/doc.go
diff --git a/libgo/go/html/doctype.go b/libgo/go/exp/html/doctype.go
index f692061a551..f692061a551 100644
--- a/libgo/go/html/doctype.go
+++ b/libgo/go/exp/html/doctype.go
diff --git a/libgo/go/exp/html/entity.go b/libgo/go/exp/html/entity.go
new file mode 100644
index 00000000000..bd830752359
--- /dev/null
+++ b/libgo/go/exp/html/entity.go
@@ -0,0 +1,2253 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+// All entities that do not end with ';' are 6 or fewer bytes long.
+const longestEntityWithoutSemicolon = 6
+
+// entity is a map from HTML entity names to their values. The semicolon matters:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html
+// lists both "amp" and "amp;" as two separate entries.
+//
+// Note that the HTML5 list is larger than the HTML4 list at
+// http://www.w3.org/TR/html4/sgml/entities.html
+var entity = map[string]rune{
+ "AElig;": '\U000000C6',
+ "AMP;": '\U00000026',
+ "Aacute;": '\U000000C1',
+ "Abreve;": '\U00000102',
+ "Acirc;": '\U000000C2',
+ "Acy;": '\U00000410',
+ "Afr;": '\U0001D504',
+ "Agrave;": '\U000000C0',
+ "Alpha;": '\U00000391',
+ "Amacr;": '\U00000100',
+ "And;": '\U00002A53',
+ "Aogon;": '\U00000104',
+ "Aopf;": '\U0001D538',
+ "ApplyFunction;": '\U00002061',
+ "Aring;": '\U000000C5',
+ "Ascr;": '\U0001D49C',
+ "Assign;": '\U00002254',
+ "Atilde;": '\U000000C3',
+ "Auml;": '\U000000C4',
+ "Backslash;": '\U00002216',
+ "Barv;": '\U00002AE7',
+ "Barwed;": '\U00002306',
+ "Bcy;": '\U00000411',
+ "Because;": '\U00002235',
+ "Bernoullis;": '\U0000212C',
+ "Beta;": '\U00000392',
+ "Bfr;": '\U0001D505',
+ "Bopf;": '\U0001D539',
+ "Breve;": '\U000002D8',
+ "Bscr;": '\U0000212C',
+ "Bumpeq;": '\U0000224E',
+ "CHcy;": '\U00000427',
+ "COPY;": '\U000000A9',
+ "Cacute;": '\U00000106',
+ "Cap;": '\U000022D2',
+ "CapitalDifferentialD;": '\U00002145',
+ "Cayleys;": '\U0000212D',
+ "Ccaron;": '\U0000010C',
+ "Ccedil;": '\U000000C7',
+ "Ccirc;": '\U00000108',
+ "Cconint;": '\U00002230',
+ "Cdot;": '\U0000010A',
+ "Cedilla;": '\U000000B8',
+ "CenterDot;": '\U000000B7',
+ "Cfr;": '\U0000212D',
+ "Chi;": '\U000003A7',
+ "CircleDot;": '\U00002299',
+ "CircleMinus;": '\U00002296',
+ "CirclePlus;": '\U00002295',
+ "CircleTimes;": '\U00002297',
+ "ClockwiseContourIntegral;": '\U00002232',
+ "CloseCurlyDoubleQuote;": '\U0000201D',
+ "CloseCurlyQuote;": '\U00002019',
+ "Colon;": '\U00002237',
+ "Colone;": '\U00002A74',
+ "Congruent;": '\U00002261',
+ "Conint;": '\U0000222F',
+ "ContourIntegral;": '\U0000222E',
+ "Copf;": '\U00002102',
+ "Coproduct;": '\U00002210',
+ "CounterClockwiseContourIntegral;": '\U00002233',
+ "Cross;": '\U00002A2F',
+ "Cscr;": '\U0001D49E',
+ "Cup;": '\U000022D3',
+ "CupCap;": '\U0000224D',
+ "DD;": '\U00002145',
+ "DDotrahd;": '\U00002911',
+ "DJcy;": '\U00000402',
+ "DScy;": '\U00000405',
+ "DZcy;": '\U0000040F',
+ "Dagger;": '\U00002021',
+ "Darr;": '\U000021A1',
+ "Dashv;": '\U00002AE4',
+ "Dcaron;": '\U0000010E',
+ "Dcy;": '\U00000414',
+ "Del;": '\U00002207',
+ "Delta;": '\U00000394',
+ "Dfr;": '\U0001D507',
+ "DiacriticalAcute;": '\U000000B4',
+ "DiacriticalDot;": '\U000002D9',
+ "DiacriticalDoubleAcute;": '\U000002DD',
+ "DiacriticalGrave;": '\U00000060',
+ "DiacriticalTilde;": '\U000002DC',
+ "Diamond;": '\U000022C4',
+ "DifferentialD;": '\U00002146',
+ "Dopf;": '\U0001D53B',
+ "Dot;": '\U000000A8',
+ "DotDot;": '\U000020DC',
+ "DotEqual;": '\U00002250',
+ "DoubleContourIntegral;": '\U0000222F',
+ "DoubleDot;": '\U000000A8',
+ "DoubleDownArrow;": '\U000021D3',
+ "DoubleLeftArrow;": '\U000021D0',
+ "DoubleLeftRightArrow;": '\U000021D4',
+ "DoubleLeftTee;": '\U00002AE4',
+ "DoubleLongLeftArrow;": '\U000027F8',
+ "DoubleLongLeftRightArrow;": '\U000027FA',
+ "DoubleLongRightArrow;": '\U000027F9',
+ "DoubleRightArrow;": '\U000021D2',
+ "DoubleRightTee;": '\U000022A8',
+ "DoubleUpArrow;": '\U000021D1',
+ "DoubleUpDownArrow;": '\U000021D5',
+ "DoubleVerticalBar;": '\U00002225',
+ "DownArrow;": '\U00002193',
+ "DownArrowBar;": '\U00002913',
+ "DownArrowUpArrow;": '\U000021F5',
+ "DownBreve;": '\U00000311',
+ "DownLeftRightVector;": '\U00002950',
+ "DownLeftTeeVector;": '\U0000295E',
+ "DownLeftVector;": '\U000021BD',
+ "DownLeftVectorBar;": '\U00002956',
+ "DownRightTeeVector;": '\U0000295F',
+ "DownRightVector;": '\U000021C1',
+ "DownRightVectorBar;": '\U00002957',
+ "DownTee;": '\U000022A4',
+ "DownTeeArrow;": '\U000021A7',
+ "Downarrow;": '\U000021D3',
+ "Dscr;": '\U0001D49F',
+ "Dstrok;": '\U00000110',
+ "ENG;": '\U0000014A',
+ "ETH;": '\U000000D0',
+ "Eacute;": '\U000000C9',
+ "Ecaron;": '\U0000011A',
+ "Ecirc;": '\U000000CA',
+ "Ecy;": '\U0000042D',
+ "Edot;": '\U00000116',
+ "Efr;": '\U0001D508',
+ "Egrave;": '\U000000C8',
+ "Element;": '\U00002208',
+ "Emacr;": '\U00000112',
+ "EmptySmallSquare;": '\U000025FB',
+ "EmptyVerySmallSquare;": '\U000025AB',
+ "Eogon;": '\U00000118',
+ "Eopf;": '\U0001D53C',
+ "Epsilon;": '\U00000395',
+ "Equal;": '\U00002A75',
+ "EqualTilde;": '\U00002242',
+ "Equilibrium;": '\U000021CC',
+ "Escr;": '\U00002130',
+ "Esim;": '\U00002A73',
+ "Eta;": '\U00000397',
+ "Euml;": '\U000000CB',
+ "Exists;": '\U00002203',
+ "ExponentialE;": '\U00002147',
+ "Fcy;": '\U00000424',
+ "Ffr;": '\U0001D509',
+ "FilledSmallSquare;": '\U000025FC',
+ "FilledVerySmallSquare;": '\U000025AA',
+ "Fopf;": '\U0001D53D',
+ "ForAll;": '\U00002200',
+ "Fouriertrf;": '\U00002131',
+ "Fscr;": '\U00002131',
+ "GJcy;": '\U00000403',
+ "GT;": '\U0000003E',
+ "Gamma;": '\U00000393',
+ "Gammad;": '\U000003DC',
+ "Gbreve;": '\U0000011E',
+ "Gcedil;": '\U00000122',
+ "Gcirc;": '\U0000011C',
+ "Gcy;": '\U00000413',
+ "Gdot;": '\U00000120',
+ "Gfr;": '\U0001D50A',
+ "Gg;": '\U000022D9',
+ "Gopf;": '\U0001D53E',
+ "GreaterEqual;": '\U00002265',
+ "GreaterEqualLess;": '\U000022DB',
+ "GreaterFullEqual;": '\U00002267',
+ "GreaterGreater;": '\U00002AA2',
+ "GreaterLess;": '\U00002277',
+ "GreaterSlantEqual;": '\U00002A7E',
+ "GreaterTilde;": '\U00002273',
+ "Gscr;": '\U0001D4A2',
+ "Gt;": '\U0000226B',
+ "HARDcy;": '\U0000042A',
+ "Hacek;": '\U000002C7',
+ "Hat;": '\U0000005E',
+ "Hcirc;": '\U00000124',
+ "Hfr;": '\U0000210C',
+ "HilbertSpace;": '\U0000210B',
+ "Hopf;": '\U0000210D',
+ "HorizontalLine;": '\U00002500',
+ "Hscr;": '\U0000210B',
+ "Hstrok;": '\U00000126',
+ "HumpDownHump;": '\U0000224E',
+ "HumpEqual;": '\U0000224F',
+ "IEcy;": '\U00000415',
+ "IJlig;": '\U00000132',
+ "IOcy;": '\U00000401',
+ "Iacute;": '\U000000CD',
+ "Icirc;": '\U000000CE',
+ "Icy;": '\U00000418',
+ "Idot;": '\U00000130',
+ "Ifr;": '\U00002111',
+ "Igrave;": '\U000000CC',
+ "Im;": '\U00002111',
+ "Imacr;": '\U0000012A',
+ "ImaginaryI;": '\U00002148',
+ "Implies;": '\U000021D2',
+ "Int;": '\U0000222C',
+ "Integral;": '\U0000222B',
+ "Intersection;": '\U000022C2',
+ "InvisibleComma;": '\U00002063',
+ "InvisibleTimes;": '\U00002062',
+ "Iogon;": '\U0000012E',
+ "Iopf;": '\U0001D540',
+ "Iota;": '\U00000399',
+ "Iscr;": '\U00002110',
+ "Itilde;": '\U00000128',
+ "Iukcy;": '\U00000406',
+ "Iuml;": '\U000000CF',
+ "Jcirc;": '\U00000134',
+ "Jcy;": '\U00000419',
+ "Jfr;": '\U0001D50D',
+ "Jopf;": '\U0001D541',
+ "Jscr;": '\U0001D4A5',
+ "Jsercy;": '\U00000408',
+ "Jukcy;": '\U00000404',
+ "KHcy;": '\U00000425',
+ "KJcy;": '\U0000040C',
+ "Kappa;": '\U0000039A',
+ "Kcedil;": '\U00000136',
+ "Kcy;": '\U0000041A',
+ "Kfr;": '\U0001D50E',
+ "Kopf;": '\U0001D542',
+ "Kscr;": '\U0001D4A6',
+ "LJcy;": '\U00000409',
+ "LT;": '\U0000003C',
+ "Lacute;": '\U00000139',
+ "Lambda;": '\U0000039B',
+ "Lang;": '\U000027EA',
+ "Laplacetrf;": '\U00002112',
+ "Larr;": '\U0000219E',
+ "Lcaron;": '\U0000013D',
+ "Lcedil;": '\U0000013B',
+ "Lcy;": '\U0000041B',
+ "LeftAngleBracket;": '\U000027E8',
+ "LeftArrow;": '\U00002190',
+ "LeftArrowBar;": '\U000021E4',
+ "LeftArrowRightArrow;": '\U000021C6',
+ "LeftCeiling;": '\U00002308',
+ "LeftDoubleBracket;": '\U000027E6',
+ "LeftDownTeeVector;": '\U00002961',
+ "LeftDownVector;": '\U000021C3',
+ "LeftDownVectorBar;": '\U00002959',
+ "LeftFloor;": '\U0000230A',
+ "LeftRightArrow;": '\U00002194',
+ "LeftRightVector;": '\U0000294E',
+ "LeftTee;": '\U000022A3',
+ "LeftTeeArrow;": '\U000021A4',
+ "LeftTeeVector;": '\U0000295A',
+ "LeftTriangle;": '\U000022B2',
+ "LeftTriangleBar;": '\U000029CF',
+ "LeftTriangleEqual;": '\U000022B4',
+ "LeftUpDownVector;": '\U00002951',
+ "LeftUpTeeVector;": '\U00002960',
+ "LeftUpVector;": '\U000021BF',
+ "LeftUpVectorBar;": '\U00002958',
+ "LeftVector;": '\U000021BC',
+ "LeftVectorBar;": '\U00002952',
+ "Leftarrow;": '\U000021D0',
+ "Leftrightarrow;": '\U000021D4',
+ "LessEqualGreater;": '\U000022DA',
+ "LessFullEqual;": '\U00002266',
+ "LessGreater;": '\U00002276',
+ "LessLess;": '\U00002AA1',
+ "LessSlantEqual;": '\U00002A7D',
+ "LessTilde;": '\U00002272',
+ "Lfr;": '\U0001D50F',
+ "Ll;": '\U000022D8',
+ "Lleftarrow;": '\U000021DA',
+ "Lmidot;": '\U0000013F',
+ "LongLeftArrow;": '\U000027F5',
+ "LongLeftRightArrow;": '\U000027F7',
+ "LongRightArrow;": '\U000027F6',
+ "Longleftarrow;": '\U000027F8',
+ "Longleftrightarrow;": '\U000027FA',
+ "Longrightarrow;": '\U000027F9',
+ "Lopf;": '\U0001D543',
+ "LowerLeftArrow;": '\U00002199',
+ "LowerRightArrow;": '\U00002198',
+ "Lscr;": '\U00002112',
+ "Lsh;": '\U000021B0',
+ "Lstrok;": '\U00000141',
+ "Lt;": '\U0000226A',
+ "Map;": '\U00002905',
+ "Mcy;": '\U0000041C',
+ "MediumSpace;": '\U0000205F',
+ "Mellintrf;": '\U00002133',
+ "Mfr;": '\U0001D510',
+ "MinusPlus;": '\U00002213',
+ "Mopf;": '\U0001D544',
+ "Mscr;": '\U00002133',
+ "Mu;": '\U0000039C',
+ "NJcy;": '\U0000040A',
+ "Nacute;": '\U00000143',
+ "Ncaron;": '\U00000147',
+ "Ncedil;": '\U00000145',
+ "Ncy;": '\U0000041D',
+ "NegativeMediumSpace;": '\U0000200B',
+ "NegativeThickSpace;": '\U0000200B',
+ "NegativeThinSpace;": '\U0000200B',
+ "NegativeVeryThinSpace;": '\U0000200B',
+ "NestedGreaterGreater;": '\U0000226B',
+ "NestedLessLess;": '\U0000226A',
+ "NewLine;": '\U0000000A',
+ "Nfr;": '\U0001D511',
+ "NoBreak;": '\U00002060',
+ "NonBreakingSpace;": '\U000000A0',
+ "Nopf;": '\U00002115',
+ "Not;": '\U00002AEC',
+ "NotCongruent;": '\U00002262',
+ "NotCupCap;": '\U0000226D',
+ "NotDoubleVerticalBar;": '\U00002226',
+ "NotElement;": '\U00002209',
+ "NotEqual;": '\U00002260',
+ "NotExists;": '\U00002204',
+ "NotGreater;": '\U0000226F',
+ "NotGreaterEqual;": '\U00002271',
+ "NotGreaterLess;": '\U00002279',
+ "NotGreaterTilde;": '\U00002275',
+ "NotLeftTriangle;": '\U000022EA',
+ "NotLeftTriangleEqual;": '\U000022EC',
+ "NotLess;": '\U0000226E',
+ "NotLessEqual;": '\U00002270',
+ "NotLessGreater;": '\U00002278',
+ "NotLessTilde;": '\U00002274',
+ "NotPrecedes;": '\U00002280',
+ "NotPrecedesSlantEqual;": '\U000022E0',
+ "NotReverseElement;": '\U0000220C',
+ "NotRightTriangle;": '\U000022EB',
+ "NotRightTriangleEqual;": '\U000022ED',
+ "NotSquareSubsetEqual;": '\U000022E2',
+ "NotSquareSupersetEqual;": '\U000022E3',
+ "NotSubsetEqual;": '\U00002288',
+ "NotSucceeds;": '\U00002281',
+ "NotSucceedsSlantEqual;": '\U000022E1',
+ "NotSupersetEqual;": '\U00002289',
+ "NotTilde;": '\U00002241',
+ "NotTildeEqual;": '\U00002244',
+ "NotTildeFullEqual;": '\U00002247',
+ "NotTildeTilde;": '\U00002249',
+ "NotVerticalBar;": '\U00002224',
+ "Nscr;": '\U0001D4A9',
+ "Ntilde;": '\U000000D1',
+ "Nu;": '\U0000039D',
+ "OElig;": '\U00000152',
+ "Oacute;": '\U000000D3',
+ "Ocirc;": '\U000000D4',
+ "Ocy;": '\U0000041E',
+ "Odblac;": '\U00000150',
+ "Ofr;": '\U0001D512',
+ "Ograve;": '\U000000D2',
+ "Omacr;": '\U0000014C',
+ "Omega;": '\U000003A9',
+ "Omicron;": '\U0000039F',
+ "Oopf;": '\U0001D546',
+ "OpenCurlyDoubleQuote;": '\U0000201C',
+ "OpenCurlyQuote;": '\U00002018',
+ "Or;": '\U00002A54',
+ "Oscr;": '\U0001D4AA',
+ "Oslash;": '\U000000D8',
+ "Otilde;": '\U000000D5',
+ "Otimes;": '\U00002A37',
+ "Ouml;": '\U000000D6',
+ "OverBar;": '\U0000203E',
+ "OverBrace;": '\U000023DE',
+ "OverBracket;": '\U000023B4',
+ "OverParenthesis;": '\U000023DC',
+ "PartialD;": '\U00002202',
+ "Pcy;": '\U0000041F',
+ "Pfr;": '\U0001D513',
+ "Phi;": '\U000003A6',
+ "Pi;": '\U000003A0',
+ "PlusMinus;": '\U000000B1',
+ "Poincareplane;": '\U0000210C',
+ "Popf;": '\U00002119',
+ "Pr;": '\U00002ABB',
+ "Precedes;": '\U0000227A',
+ "PrecedesEqual;": '\U00002AAF',
+ "PrecedesSlantEqual;": '\U0000227C',
+ "PrecedesTilde;": '\U0000227E',
+ "Prime;": '\U00002033',
+ "Product;": '\U0000220F',
+ "Proportion;": '\U00002237',
+ "Proportional;": '\U0000221D',
+ "Pscr;": '\U0001D4AB',
+ "Psi;": '\U000003A8',
+ "QUOT;": '\U00000022',
+ "Qfr;": '\U0001D514',
+ "Qopf;": '\U0000211A',
+ "Qscr;": '\U0001D4AC',
+ "RBarr;": '\U00002910',
+ "REG;": '\U000000AE',
+ "Racute;": '\U00000154',
+ "Rang;": '\U000027EB',
+ "Rarr;": '\U000021A0',
+ "Rarrtl;": '\U00002916',
+ "Rcaron;": '\U00000158',
+ "Rcedil;": '\U00000156',
+ "Rcy;": '\U00000420',
+ "Re;": '\U0000211C',
+ "ReverseElement;": '\U0000220B',
+ "ReverseEquilibrium;": '\U000021CB',
+ "ReverseUpEquilibrium;": '\U0000296F',
+ "Rfr;": '\U0000211C',
+ "Rho;": '\U000003A1',
+ "RightAngleBracket;": '\U000027E9',
+ "RightArrow;": '\U00002192',
+ "RightArrowBar;": '\U000021E5',
+ "RightArrowLeftArrow;": '\U000021C4',
+ "RightCeiling;": '\U00002309',
+ "RightDoubleBracket;": '\U000027E7',
+ "RightDownTeeVector;": '\U0000295D',
+ "RightDownVector;": '\U000021C2',
+ "RightDownVectorBar;": '\U00002955',
+ "RightFloor;": '\U0000230B',
+ "RightTee;": '\U000022A2',
+ "RightTeeArrow;": '\U000021A6',
+ "RightTeeVector;": '\U0000295B',
+ "RightTriangle;": '\U000022B3',
+ "RightTriangleBar;": '\U000029D0',
+ "RightTriangleEqual;": '\U000022B5',
+ "RightUpDownVector;": '\U0000294F',
+ "RightUpTeeVector;": '\U0000295C',
+ "RightUpVector;": '\U000021BE',
+ "RightUpVectorBar;": '\U00002954',
+ "RightVector;": '\U000021C0',
+ "RightVectorBar;": '\U00002953',
+ "Rightarrow;": '\U000021D2',
+ "Ropf;": '\U0000211D',
+ "RoundImplies;": '\U00002970',
+ "Rrightarrow;": '\U000021DB',
+ "Rscr;": '\U0000211B',
+ "Rsh;": '\U000021B1',
+ "RuleDelayed;": '\U000029F4',
+ "SHCHcy;": '\U00000429',
+ "SHcy;": '\U00000428',
+ "SOFTcy;": '\U0000042C',
+ "Sacute;": '\U0000015A',
+ "Sc;": '\U00002ABC',
+ "Scaron;": '\U00000160',
+ "Scedil;": '\U0000015E',
+ "Scirc;": '\U0000015C',
+ "Scy;": '\U00000421',
+ "Sfr;": '\U0001D516',
+ "ShortDownArrow;": '\U00002193',
+ "ShortLeftArrow;": '\U00002190',
+ "ShortRightArrow;": '\U00002192',
+ "ShortUpArrow;": '\U00002191',
+ "Sigma;": '\U000003A3',
+ "SmallCircle;": '\U00002218',
+ "Sopf;": '\U0001D54A',
+ "Sqrt;": '\U0000221A',
+ "Square;": '\U000025A1',
+ "SquareIntersection;": '\U00002293',
+ "SquareSubset;": '\U0000228F',
+ "SquareSubsetEqual;": '\U00002291',
+ "SquareSuperset;": '\U00002290',
+ "SquareSupersetEqual;": '\U00002292',
+ "SquareUnion;": '\U00002294',
+ "Sscr;": '\U0001D4AE',
+ "Star;": '\U000022C6',
+ "Sub;": '\U000022D0',
+ "Subset;": '\U000022D0',
+ "SubsetEqual;": '\U00002286',
+ "Succeeds;": '\U0000227B',
+ "SucceedsEqual;": '\U00002AB0',
+ "SucceedsSlantEqual;": '\U0000227D',
+ "SucceedsTilde;": '\U0000227F',
+ "SuchThat;": '\U0000220B',
+ "Sum;": '\U00002211',
+ "Sup;": '\U000022D1',
+ "Superset;": '\U00002283',
+ "SupersetEqual;": '\U00002287',
+ "Supset;": '\U000022D1',
+ "THORN;": '\U000000DE',
+ "TRADE;": '\U00002122',
+ "TSHcy;": '\U0000040B',
+ "TScy;": '\U00000426',
+ "Tab;": '\U00000009',
+ "Tau;": '\U000003A4',
+ "Tcaron;": '\U00000164',
+ "Tcedil;": '\U00000162',
+ "Tcy;": '\U00000422',
+ "Tfr;": '\U0001D517',
+ "Therefore;": '\U00002234',
+ "Theta;": '\U00000398',
+ "ThinSpace;": '\U00002009',
+ "Tilde;": '\U0000223C',
+ "TildeEqual;": '\U00002243',
+ "TildeFullEqual;": '\U00002245',
+ "TildeTilde;": '\U00002248',
+ "Topf;": '\U0001D54B',
+ "TripleDot;": '\U000020DB',
+ "Tscr;": '\U0001D4AF',
+ "Tstrok;": '\U00000166',
+ "Uacute;": '\U000000DA',
+ "Uarr;": '\U0000219F',
+ "Uarrocir;": '\U00002949',
+ "Ubrcy;": '\U0000040E',
+ "Ubreve;": '\U0000016C',
+ "Ucirc;": '\U000000DB',
+ "Ucy;": '\U00000423',
+ "Udblac;": '\U00000170',
+ "Ufr;": '\U0001D518',
+ "Ugrave;": '\U000000D9',
+ "Umacr;": '\U0000016A',
+ "UnderBar;": '\U0000005F',
+ "UnderBrace;": '\U000023DF',
+ "UnderBracket;": '\U000023B5',
+ "UnderParenthesis;": '\U000023DD',
+ "Union;": '\U000022C3',
+ "UnionPlus;": '\U0000228E',
+ "Uogon;": '\U00000172',
+ "Uopf;": '\U0001D54C',
+ "UpArrow;": '\U00002191',
+ "UpArrowBar;": '\U00002912',
+ "UpArrowDownArrow;": '\U000021C5',
+ "UpDownArrow;": '\U00002195',
+ "UpEquilibrium;": '\U0000296E',
+ "UpTee;": '\U000022A5',
+ "UpTeeArrow;": '\U000021A5',
+ "Uparrow;": '\U000021D1',
+ "Updownarrow;": '\U000021D5',
+ "UpperLeftArrow;": '\U00002196',
+ "UpperRightArrow;": '\U00002197',
+ "Upsi;": '\U000003D2',
+ "Upsilon;": '\U000003A5',
+ "Uring;": '\U0000016E',
+ "Uscr;": '\U0001D4B0',
+ "Utilde;": '\U00000168',
+ "Uuml;": '\U000000DC',
+ "VDash;": '\U000022AB',
+ "Vbar;": '\U00002AEB',
+ "Vcy;": '\U00000412',
+ "Vdash;": '\U000022A9',
+ "Vdashl;": '\U00002AE6',
+ "Vee;": '\U000022C1',
+ "Verbar;": '\U00002016',
+ "Vert;": '\U00002016',
+ "VerticalBar;": '\U00002223',
+ "VerticalLine;": '\U0000007C',
+ "VerticalSeparator;": '\U00002758',
+ "VerticalTilde;": '\U00002240',
+ "VeryThinSpace;": '\U0000200A',
+ "Vfr;": '\U0001D519',
+ "Vopf;": '\U0001D54D',
+ "Vscr;": '\U0001D4B1',
+ "Vvdash;": '\U000022AA',
+ "Wcirc;": '\U00000174',
+ "Wedge;": '\U000022C0',
+ "Wfr;": '\U0001D51A',
+ "Wopf;": '\U0001D54E',
+ "Wscr;": '\U0001D4B2',
+ "Xfr;": '\U0001D51B',
+ "Xi;": '\U0000039E',
+ "Xopf;": '\U0001D54F',
+ "Xscr;": '\U0001D4B3',
+ "YAcy;": '\U0000042F',
+ "YIcy;": '\U00000407',
+ "YUcy;": '\U0000042E',
+ "Yacute;": '\U000000DD',
+ "Ycirc;": '\U00000176',
+ "Ycy;": '\U0000042B',
+ "Yfr;": '\U0001D51C',
+ "Yopf;": '\U0001D550',
+ "Yscr;": '\U0001D4B4',
+ "Yuml;": '\U00000178',
+ "ZHcy;": '\U00000416',
+ "Zacute;": '\U00000179',
+ "Zcaron;": '\U0000017D',
+ "Zcy;": '\U00000417',
+ "Zdot;": '\U0000017B',
+ "ZeroWidthSpace;": '\U0000200B',
+ "Zeta;": '\U00000396',
+ "Zfr;": '\U00002128',
+ "Zopf;": '\U00002124',
+ "Zscr;": '\U0001D4B5',
+ "aacute;": '\U000000E1',
+ "abreve;": '\U00000103',
+ "ac;": '\U0000223E',
+ "acd;": '\U0000223F',
+ "acirc;": '\U000000E2',
+ "acute;": '\U000000B4',
+ "acy;": '\U00000430',
+ "aelig;": '\U000000E6',
+ "af;": '\U00002061',
+ "afr;": '\U0001D51E',
+ "agrave;": '\U000000E0',
+ "alefsym;": '\U00002135',
+ "aleph;": '\U00002135',
+ "alpha;": '\U000003B1',
+ "amacr;": '\U00000101',
+ "amalg;": '\U00002A3F',
+ "amp;": '\U00000026',
+ "and;": '\U00002227',
+ "andand;": '\U00002A55',
+ "andd;": '\U00002A5C',
+ "andslope;": '\U00002A58',
+ "andv;": '\U00002A5A',
+ "ang;": '\U00002220',
+ "ange;": '\U000029A4',
+ "angle;": '\U00002220',
+ "angmsd;": '\U00002221',
+ "angmsdaa;": '\U000029A8',
+ "angmsdab;": '\U000029A9',
+ "angmsdac;": '\U000029AA',
+ "angmsdad;": '\U000029AB',
+ "angmsdae;": '\U000029AC',
+ "angmsdaf;": '\U000029AD',
+ "angmsdag;": '\U000029AE',
+ "angmsdah;": '\U000029AF',
+ "angrt;": '\U0000221F',
+ "angrtvb;": '\U000022BE',
+ "angrtvbd;": '\U0000299D',
+ "angsph;": '\U00002222',
+ "angst;": '\U000000C5',
+ "angzarr;": '\U0000237C',
+ "aogon;": '\U00000105',
+ "aopf;": '\U0001D552',
+ "ap;": '\U00002248',
+ "apE;": '\U00002A70',
+ "apacir;": '\U00002A6F',
+ "ape;": '\U0000224A',
+ "apid;": '\U0000224B',
+ "apos;": '\U00000027',
+ "approx;": '\U00002248',
+ "approxeq;": '\U0000224A',
+ "aring;": '\U000000E5',
+ "ascr;": '\U0001D4B6',
+ "ast;": '\U0000002A',
+ "asymp;": '\U00002248',
+ "asympeq;": '\U0000224D',
+ "atilde;": '\U000000E3',
+ "auml;": '\U000000E4',
+ "awconint;": '\U00002233',
+ "awint;": '\U00002A11',
+ "bNot;": '\U00002AED',
+ "backcong;": '\U0000224C',
+ "backepsilon;": '\U000003F6',
+ "backprime;": '\U00002035',
+ "backsim;": '\U0000223D',
+ "backsimeq;": '\U000022CD',
+ "barvee;": '\U000022BD',
+ "barwed;": '\U00002305',
+ "barwedge;": '\U00002305',
+ "bbrk;": '\U000023B5',
+ "bbrktbrk;": '\U000023B6',
+ "bcong;": '\U0000224C',
+ "bcy;": '\U00000431',
+ "bdquo;": '\U0000201E',
+ "becaus;": '\U00002235',
+ "because;": '\U00002235',
+ "bemptyv;": '\U000029B0',
+ "bepsi;": '\U000003F6',
+ "bernou;": '\U0000212C',
+ "beta;": '\U000003B2',
+ "beth;": '\U00002136',
+ "between;": '\U0000226C',
+ "bfr;": '\U0001D51F',
+ "bigcap;": '\U000022C2',
+ "bigcirc;": '\U000025EF',
+ "bigcup;": '\U000022C3',
+ "bigodot;": '\U00002A00',
+ "bigoplus;": '\U00002A01',
+ "bigotimes;": '\U00002A02',
+ "bigsqcup;": '\U00002A06',
+ "bigstar;": '\U00002605',
+ "bigtriangledown;": '\U000025BD',
+ "bigtriangleup;": '\U000025B3',
+ "biguplus;": '\U00002A04',
+ "bigvee;": '\U000022C1',
+ "bigwedge;": '\U000022C0',
+ "bkarow;": '\U0000290D',
+ "blacklozenge;": '\U000029EB',
+ "blacksquare;": '\U000025AA',
+ "blacktriangle;": '\U000025B4',
+ "blacktriangledown;": '\U000025BE',
+ "blacktriangleleft;": '\U000025C2',
+ "blacktriangleright;": '\U000025B8',
+ "blank;": '\U00002423',
+ "blk12;": '\U00002592',
+ "blk14;": '\U00002591',
+ "blk34;": '\U00002593',
+ "block;": '\U00002588',
+ "bnot;": '\U00002310',
+ "bopf;": '\U0001D553',
+ "bot;": '\U000022A5',
+ "bottom;": '\U000022A5',
+ "bowtie;": '\U000022C8',
+ "boxDL;": '\U00002557',
+ "boxDR;": '\U00002554',
+ "boxDl;": '\U00002556',
+ "boxDr;": '\U00002553',
+ "boxH;": '\U00002550',
+ "boxHD;": '\U00002566',
+ "boxHU;": '\U00002569',
+ "boxHd;": '\U00002564',
+ "boxHu;": '\U00002567',
+ "boxUL;": '\U0000255D',
+ "boxUR;": '\U0000255A',
+ "boxUl;": '\U0000255C',
+ "boxUr;": '\U00002559',
+ "boxV;": '\U00002551',
+ "boxVH;": '\U0000256C',
+ "boxVL;": '\U00002563',
+ "boxVR;": '\U00002560',
+ "boxVh;": '\U0000256B',
+ "boxVl;": '\U00002562',
+ "boxVr;": '\U0000255F',
+ "boxbox;": '\U000029C9',
+ "boxdL;": '\U00002555',
+ "boxdR;": '\U00002552',
+ "boxdl;": '\U00002510',
+ "boxdr;": '\U0000250C',
+ "boxh;": '\U00002500',
+ "boxhD;": '\U00002565',
+ "boxhU;": '\U00002568',
+ "boxhd;": '\U0000252C',
+ "boxhu;": '\U00002534',
+ "boxminus;": '\U0000229F',
+ "boxplus;": '\U0000229E',
+ "boxtimes;": '\U000022A0',
+ "boxuL;": '\U0000255B',
+ "boxuR;": '\U00002558',
+ "boxul;": '\U00002518',
+ "boxur;": '\U00002514',
+ "boxv;": '\U00002502',
+ "boxvH;": '\U0000256A',
+ "boxvL;": '\U00002561',
+ "boxvR;": '\U0000255E',
+ "boxvh;": '\U0000253C',
+ "boxvl;": '\U00002524',
+ "boxvr;": '\U0000251C',
+ "bprime;": '\U00002035',
+ "breve;": '\U000002D8',
+ "brvbar;": '\U000000A6',
+ "bscr;": '\U0001D4B7',
+ "bsemi;": '\U0000204F',
+ "bsim;": '\U0000223D',
+ "bsime;": '\U000022CD',
+ "bsol;": '\U0000005C',
+ "bsolb;": '\U000029C5',
+ "bsolhsub;": '\U000027C8',
+ "bull;": '\U00002022',
+ "bullet;": '\U00002022',
+ "bump;": '\U0000224E',
+ "bumpE;": '\U00002AAE',
+ "bumpe;": '\U0000224F',
+ "bumpeq;": '\U0000224F',
+ "cacute;": '\U00000107',
+ "cap;": '\U00002229',
+ "capand;": '\U00002A44',
+ "capbrcup;": '\U00002A49',
+ "capcap;": '\U00002A4B',
+ "capcup;": '\U00002A47',
+ "capdot;": '\U00002A40',
+ "caret;": '\U00002041',
+ "caron;": '\U000002C7',
+ "ccaps;": '\U00002A4D',
+ "ccaron;": '\U0000010D',
+ "ccedil;": '\U000000E7',
+ "ccirc;": '\U00000109',
+ "ccups;": '\U00002A4C',
+ "ccupssm;": '\U00002A50',
+ "cdot;": '\U0000010B',
+ "cedil;": '\U000000B8',
+ "cemptyv;": '\U000029B2',
+ "cent;": '\U000000A2',
+ "centerdot;": '\U000000B7',
+ "cfr;": '\U0001D520',
+ "chcy;": '\U00000447',
+ "check;": '\U00002713',
+ "checkmark;": '\U00002713',
+ "chi;": '\U000003C7',
+ "cir;": '\U000025CB',
+ "cirE;": '\U000029C3',
+ "circ;": '\U000002C6',
+ "circeq;": '\U00002257',
+ "circlearrowleft;": '\U000021BA',
+ "circlearrowright;": '\U000021BB',
+ "circledR;": '\U000000AE',
+ "circledS;": '\U000024C8',
+ "circledast;": '\U0000229B',
+ "circledcirc;": '\U0000229A',
+ "circleddash;": '\U0000229D',
+ "cire;": '\U00002257',
+ "cirfnint;": '\U00002A10',
+ "cirmid;": '\U00002AEF',
+ "cirscir;": '\U000029C2',
+ "clubs;": '\U00002663',
+ "clubsuit;": '\U00002663',
+ "colon;": '\U0000003A',
+ "colone;": '\U00002254',
+ "coloneq;": '\U00002254',
+ "comma;": '\U0000002C',
+ "commat;": '\U00000040',
+ "comp;": '\U00002201',
+ "compfn;": '\U00002218',
+ "complement;": '\U00002201',
+ "complexes;": '\U00002102',
+ "cong;": '\U00002245',
+ "congdot;": '\U00002A6D',
+ "conint;": '\U0000222E',
+ "copf;": '\U0001D554',
+ "coprod;": '\U00002210',
+ "copy;": '\U000000A9',
+ "copysr;": '\U00002117',
+ "crarr;": '\U000021B5',
+ "cross;": '\U00002717',
+ "cscr;": '\U0001D4B8',
+ "csub;": '\U00002ACF',
+ "csube;": '\U00002AD1',
+ "csup;": '\U00002AD0',
+ "csupe;": '\U00002AD2',
+ "ctdot;": '\U000022EF',
+ "cudarrl;": '\U00002938',
+ "cudarrr;": '\U00002935',
+ "cuepr;": '\U000022DE',
+ "cuesc;": '\U000022DF',
+ "cularr;": '\U000021B6',
+ "cularrp;": '\U0000293D',
+ "cup;": '\U0000222A',
+ "cupbrcap;": '\U00002A48',
+ "cupcap;": '\U00002A46',
+ "cupcup;": '\U00002A4A',
+ "cupdot;": '\U0000228D',
+ "cupor;": '\U00002A45',
+ "curarr;": '\U000021B7',
+ "curarrm;": '\U0000293C',
+ "curlyeqprec;": '\U000022DE',
+ "curlyeqsucc;": '\U000022DF',
+ "curlyvee;": '\U000022CE',
+ "curlywedge;": '\U000022CF',
+ "curren;": '\U000000A4',
+ "curvearrowleft;": '\U000021B6',
+ "curvearrowright;": '\U000021B7',
+ "cuvee;": '\U000022CE',
+ "cuwed;": '\U000022CF',
+ "cwconint;": '\U00002232',
+ "cwint;": '\U00002231',
+ "cylcty;": '\U0000232D',
+ "dArr;": '\U000021D3',
+ "dHar;": '\U00002965',
+ "dagger;": '\U00002020',
+ "daleth;": '\U00002138',
+ "darr;": '\U00002193',
+ "dash;": '\U00002010',
+ "dashv;": '\U000022A3',
+ "dbkarow;": '\U0000290F',
+ "dblac;": '\U000002DD',
+ "dcaron;": '\U0000010F',
+ "dcy;": '\U00000434',
+ "dd;": '\U00002146',
+ "ddagger;": '\U00002021',
+ "ddarr;": '\U000021CA',
+ "ddotseq;": '\U00002A77',
+ "deg;": '\U000000B0',
+ "delta;": '\U000003B4',
+ "demptyv;": '\U000029B1',
+ "dfisht;": '\U0000297F',
+ "dfr;": '\U0001D521',
+ "dharl;": '\U000021C3',
+ "dharr;": '\U000021C2',
+ "diam;": '\U000022C4',
+ "diamond;": '\U000022C4',
+ "diamondsuit;": '\U00002666',
+ "diams;": '\U00002666',
+ "die;": '\U000000A8',
+ "digamma;": '\U000003DD',
+ "disin;": '\U000022F2',
+ "div;": '\U000000F7',
+ "divide;": '\U000000F7',
+ "divideontimes;": '\U000022C7',
+ "divonx;": '\U000022C7',
+ "djcy;": '\U00000452',
+ "dlcorn;": '\U0000231E',
+ "dlcrop;": '\U0000230D',
+ "dollar;": '\U00000024',
+ "dopf;": '\U0001D555',
+ "dot;": '\U000002D9',
+ "doteq;": '\U00002250',
+ "doteqdot;": '\U00002251',
+ "dotminus;": '\U00002238',
+ "dotplus;": '\U00002214',
+ "dotsquare;": '\U000022A1',
+ "doublebarwedge;": '\U00002306',
+ "downarrow;": '\U00002193',
+ "downdownarrows;": '\U000021CA',
+ "downharpoonleft;": '\U000021C3',
+ "downharpoonright;": '\U000021C2',
+ "drbkarow;": '\U00002910',
+ "drcorn;": '\U0000231F',
+ "drcrop;": '\U0000230C',
+ "dscr;": '\U0001D4B9',
+ "dscy;": '\U00000455',
+ "dsol;": '\U000029F6',
+ "dstrok;": '\U00000111',
+ "dtdot;": '\U000022F1',
+ "dtri;": '\U000025BF',
+ "dtrif;": '\U000025BE',
+ "duarr;": '\U000021F5',
+ "duhar;": '\U0000296F',
+ "dwangle;": '\U000029A6',
+ "dzcy;": '\U0000045F',
+ "dzigrarr;": '\U000027FF',
+ "eDDot;": '\U00002A77',
+ "eDot;": '\U00002251',
+ "eacute;": '\U000000E9',
+ "easter;": '\U00002A6E',
+ "ecaron;": '\U0000011B',
+ "ecir;": '\U00002256',
+ "ecirc;": '\U000000EA',
+ "ecolon;": '\U00002255',
+ "ecy;": '\U0000044D',
+ "edot;": '\U00000117',
+ "ee;": '\U00002147',
+ "efDot;": '\U00002252',
+ "efr;": '\U0001D522',
+ "eg;": '\U00002A9A',
+ "egrave;": '\U000000E8',
+ "egs;": '\U00002A96',
+ "egsdot;": '\U00002A98',
+ "el;": '\U00002A99',
+ "elinters;": '\U000023E7',
+ "ell;": '\U00002113',
+ "els;": '\U00002A95',
+ "elsdot;": '\U00002A97',
+ "emacr;": '\U00000113',
+ "empty;": '\U00002205',
+ "emptyset;": '\U00002205',
+ "emptyv;": '\U00002205',
+ "emsp;": '\U00002003',
+ "emsp13;": '\U00002004',
+ "emsp14;": '\U00002005',
+ "eng;": '\U0000014B',
+ "ensp;": '\U00002002',
+ "eogon;": '\U00000119',
+ "eopf;": '\U0001D556',
+ "epar;": '\U000022D5',
+ "eparsl;": '\U000029E3',
+ "eplus;": '\U00002A71',
+ "epsi;": '\U000003B5',
+ "epsilon;": '\U000003B5',
+ "epsiv;": '\U000003F5',
+ "eqcirc;": '\U00002256',
+ "eqcolon;": '\U00002255',
+ "eqsim;": '\U00002242',
+ "eqslantgtr;": '\U00002A96',
+ "eqslantless;": '\U00002A95',
+ "equals;": '\U0000003D',
+ "equest;": '\U0000225F',
+ "equiv;": '\U00002261',
+ "equivDD;": '\U00002A78',
+ "eqvparsl;": '\U000029E5',
+ "erDot;": '\U00002253',
+ "erarr;": '\U00002971',
+ "escr;": '\U0000212F',
+ "esdot;": '\U00002250',
+ "esim;": '\U00002242',
+ "eta;": '\U000003B7',
+ "eth;": '\U000000F0',
+ "euml;": '\U000000EB',
+ "euro;": '\U000020AC',
+ "excl;": '\U00000021',
+ "exist;": '\U00002203',
+ "expectation;": '\U00002130',
+ "exponentiale;": '\U00002147',
+ "fallingdotseq;": '\U00002252',
+ "fcy;": '\U00000444',
+ "female;": '\U00002640',
+ "ffilig;": '\U0000FB03',
+ "fflig;": '\U0000FB00',
+ "ffllig;": '\U0000FB04',
+ "ffr;": '\U0001D523',
+ "filig;": '\U0000FB01',
+ "flat;": '\U0000266D',
+ "fllig;": '\U0000FB02',
+ "fltns;": '\U000025B1',
+ "fnof;": '\U00000192',
+ "fopf;": '\U0001D557',
+ "forall;": '\U00002200',
+ "fork;": '\U000022D4',
+ "forkv;": '\U00002AD9',
+ "fpartint;": '\U00002A0D',
+ "frac12;": '\U000000BD',
+ "frac13;": '\U00002153',
+ "frac14;": '\U000000BC',
+ "frac15;": '\U00002155',
+ "frac16;": '\U00002159',
+ "frac18;": '\U0000215B',
+ "frac23;": '\U00002154',
+ "frac25;": '\U00002156',
+ "frac34;": '\U000000BE',
+ "frac35;": '\U00002157',
+ "frac38;": '\U0000215C',
+ "frac45;": '\U00002158',
+ "frac56;": '\U0000215A',
+ "frac58;": '\U0000215D',
+ "frac78;": '\U0000215E',
+ "frasl;": '\U00002044',
+ "frown;": '\U00002322',
+ "fscr;": '\U0001D4BB',
+ "gE;": '\U00002267',
+ "gEl;": '\U00002A8C',
+ "gacute;": '\U000001F5',
+ "gamma;": '\U000003B3',
+ "gammad;": '\U000003DD',
+ "gap;": '\U00002A86',
+ "gbreve;": '\U0000011F',
+ "gcirc;": '\U0000011D',
+ "gcy;": '\U00000433',
+ "gdot;": '\U00000121',
+ "ge;": '\U00002265',
+ "gel;": '\U000022DB',
+ "geq;": '\U00002265',
+ "geqq;": '\U00002267',
+ "geqslant;": '\U00002A7E',
+ "ges;": '\U00002A7E',
+ "gescc;": '\U00002AA9',
+ "gesdot;": '\U00002A80',
+ "gesdoto;": '\U00002A82',
+ "gesdotol;": '\U00002A84',
+ "gesles;": '\U00002A94',
+ "gfr;": '\U0001D524',
+ "gg;": '\U0000226B',
+ "ggg;": '\U000022D9',
+ "gimel;": '\U00002137',
+ "gjcy;": '\U00000453',
+ "gl;": '\U00002277',
+ "glE;": '\U00002A92',
+ "gla;": '\U00002AA5',
+ "glj;": '\U00002AA4',
+ "gnE;": '\U00002269',
+ "gnap;": '\U00002A8A',
+ "gnapprox;": '\U00002A8A',
+ "gne;": '\U00002A88',
+ "gneq;": '\U00002A88',
+ "gneqq;": '\U00002269',
+ "gnsim;": '\U000022E7',
+ "gopf;": '\U0001D558',
+ "grave;": '\U00000060',
+ "gscr;": '\U0000210A',
+ "gsim;": '\U00002273',
+ "gsime;": '\U00002A8E',
+ "gsiml;": '\U00002A90',
+ "gt;": '\U0000003E',
+ "gtcc;": '\U00002AA7',
+ "gtcir;": '\U00002A7A',
+ "gtdot;": '\U000022D7',
+ "gtlPar;": '\U00002995',
+ "gtquest;": '\U00002A7C',
+ "gtrapprox;": '\U00002A86',
+ "gtrarr;": '\U00002978',
+ "gtrdot;": '\U000022D7',
+ "gtreqless;": '\U000022DB',
+ "gtreqqless;": '\U00002A8C',
+ "gtrless;": '\U00002277',
+ "gtrsim;": '\U00002273',
+ "hArr;": '\U000021D4',
+ "hairsp;": '\U0000200A',
+ "half;": '\U000000BD',
+ "hamilt;": '\U0000210B',
+ "hardcy;": '\U0000044A',
+ "harr;": '\U00002194',
+ "harrcir;": '\U00002948',
+ "harrw;": '\U000021AD',
+ "hbar;": '\U0000210F',
+ "hcirc;": '\U00000125',
+ "hearts;": '\U00002665',
+ "heartsuit;": '\U00002665',
+ "hellip;": '\U00002026',
+ "hercon;": '\U000022B9',
+ "hfr;": '\U0001D525',
+ "hksearow;": '\U00002925',
+ "hkswarow;": '\U00002926',
+ "hoarr;": '\U000021FF',
+ "homtht;": '\U0000223B',
+ "hookleftarrow;": '\U000021A9',
+ "hookrightarrow;": '\U000021AA',
+ "hopf;": '\U0001D559',
+ "horbar;": '\U00002015',
+ "hscr;": '\U0001D4BD',
+ "hslash;": '\U0000210F',
+ "hstrok;": '\U00000127',
+ "hybull;": '\U00002043',
+ "hyphen;": '\U00002010',
+ "iacute;": '\U000000ED',
+ "ic;": '\U00002063',
+ "icirc;": '\U000000EE',
+ "icy;": '\U00000438',
+ "iecy;": '\U00000435',
+ "iexcl;": '\U000000A1',
+ "iff;": '\U000021D4',
+ "ifr;": '\U0001D526',
+ "igrave;": '\U000000EC',
+ "ii;": '\U00002148',
+ "iiiint;": '\U00002A0C',
+ "iiint;": '\U0000222D',
+ "iinfin;": '\U000029DC',
+ "iiota;": '\U00002129',
+ "ijlig;": '\U00000133',
+ "imacr;": '\U0000012B',
+ "image;": '\U00002111',
+ "imagline;": '\U00002110',
+ "imagpart;": '\U00002111',
+ "imath;": '\U00000131',
+ "imof;": '\U000022B7',
+ "imped;": '\U000001B5',
+ "in;": '\U00002208',
+ "incare;": '\U00002105',
+ "infin;": '\U0000221E',
+ "infintie;": '\U000029DD',
+ "inodot;": '\U00000131',
+ "int;": '\U0000222B',
+ "intcal;": '\U000022BA',
+ "integers;": '\U00002124',
+ "intercal;": '\U000022BA',
+ "intlarhk;": '\U00002A17',
+ "intprod;": '\U00002A3C',
+ "iocy;": '\U00000451',
+ "iogon;": '\U0000012F',
+ "iopf;": '\U0001D55A',
+ "iota;": '\U000003B9',
+ "iprod;": '\U00002A3C',
+ "iquest;": '\U000000BF',
+ "iscr;": '\U0001D4BE',
+ "isin;": '\U00002208',
+ "isinE;": '\U000022F9',
+ "isindot;": '\U000022F5',
+ "isins;": '\U000022F4',
+ "isinsv;": '\U000022F3',
+ "isinv;": '\U00002208',
+ "it;": '\U00002062',
+ "itilde;": '\U00000129',
+ "iukcy;": '\U00000456',
+ "iuml;": '\U000000EF',
+ "jcirc;": '\U00000135',
+ "jcy;": '\U00000439',
+ "jfr;": '\U0001D527',
+ "jmath;": '\U00000237',
+ "jopf;": '\U0001D55B',
+ "jscr;": '\U0001D4BF',
+ "jsercy;": '\U00000458',
+ "jukcy;": '\U00000454',
+ "kappa;": '\U000003BA',
+ "kappav;": '\U000003F0',
+ "kcedil;": '\U00000137',
+ "kcy;": '\U0000043A',
+ "kfr;": '\U0001D528',
+ "kgreen;": '\U00000138',
+ "khcy;": '\U00000445',
+ "kjcy;": '\U0000045C',
+ "kopf;": '\U0001D55C',
+ "kscr;": '\U0001D4C0',
+ "lAarr;": '\U000021DA',
+ "lArr;": '\U000021D0',
+ "lAtail;": '\U0000291B',
+ "lBarr;": '\U0000290E',
+ "lE;": '\U00002266',
+ "lEg;": '\U00002A8B',
+ "lHar;": '\U00002962',
+ "lacute;": '\U0000013A',
+ "laemptyv;": '\U000029B4',
+ "lagran;": '\U00002112',
+ "lambda;": '\U000003BB',
+ "lang;": '\U000027E8',
+ "langd;": '\U00002991',
+ "langle;": '\U000027E8',
+ "lap;": '\U00002A85',
+ "laquo;": '\U000000AB',
+ "larr;": '\U00002190',
+ "larrb;": '\U000021E4',
+ "larrbfs;": '\U0000291F',
+ "larrfs;": '\U0000291D',
+ "larrhk;": '\U000021A9',
+ "larrlp;": '\U000021AB',
+ "larrpl;": '\U00002939',
+ "larrsim;": '\U00002973',
+ "larrtl;": '\U000021A2',
+ "lat;": '\U00002AAB',
+ "latail;": '\U00002919',
+ "late;": '\U00002AAD',
+ "lbarr;": '\U0000290C',
+ "lbbrk;": '\U00002772',
+ "lbrace;": '\U0000007B',
+ "lbrack;": '\U0000005B',
+ "lbrke;": '\U0000298B',
+ "lbrksld;": '\U0000298F',
+ "lbrkslu;": '\U0000298D',
+ "lcaron;": '\U0000013E',
+ "lcedil;": '\U0000013C',
+ "lceil;": '\U00002308',
+ "lcub;": '\U0000007B',
+ "lcy;": '\U0000043B',
+ "ldca;": '\U00002936',
+ "ldquo;": '\U0000201C',
+ "ldquor;": '\U0000201E',
+ "ldrdhar;": '\U00002967',
+ "ldrushar;": '\U0000294B',
+ "ldsh;": '\U000021B2',
+ "le;": '\U00002264',
+ "leftarrow;": '\U00002190',
+ "leftarrowtail;": '\U000021A2',
+ "leftharpoondown;": '\U000021BD',
+ "leftharpoonup;": '\U000021BC',
+ "leftleftarrows;": '\U000021C7',
+ "leftrightarrow;": '\U00002194',
+ "leftrightarrows;": '\U000021C6',
+ "leftrightharpoons;": '\U000021CB',
+ "leftrightsquigarrow;": '\U000021AD',
+ "leftthreetimes;": '\U000022CB',
+ "leg;": '\U000022DA',
+ "leq;": '\U00002264',
+ "leqq;": '\U00002266',
+ "leqslant;": '\U00002A7D',
+ "les;": '\U00002A7D',
+ "lescc;": '\U00002AA8',
+ "lesdot;": '\U00002A7F',
+ "lesdoto;": '\U00002A81',
+ "lesdotor;": '\U00002A83',
+ "lesges;": '\U00002A93',
+ "lessapprox;": '\U00002A85',
+ "lessdot;": '\U000022D6',
+ "lesseqgtr;": '\U000022DA',
+ "lesseqqgtr;": '\U00002A8B',
+ "lessgtr;": '\U00002276',
+ "lesssim;": '\U00002272',
+ "lfisht;": '\U0000297C',
+ "lfloor;": '\U0000230A',
+ "lfr;": '\U0001D529',
+ "lg;": '\U00002276',
+ "lgE;": '\U00002A91',
+ "lhard;": '\U000021BD',
+ "lharu;": '\U000021BC',
+ "lharul;": '\U0000296A',
+ "lhblk;": '\U00002584',
+ "ljcy;": '\U00000459',
+ "ll;": '\U0000226A',
+ "llarr;": '\U000021C7',
+ "llcorner;": '\U0000231E',
+ "llhard;": '\U0000296B',
+ "lltri;": '\U000025FA',
+ "lmidot;": '\U00000140',
+ "lmoust;": '\U000023B0',
+ "lmoustache;": '\U000023B0',
+ "lnE;": '\U00002268',
+ "lnap;": '\U00002A89',
+ "lnapprox;": '\U00002A89',
+ "lne;": '\U00002A87',
+ "lneq;": '\U00002A87',
+ "lneqq;": '\U00002268',
+ "lnsim;": '\U000022E6',
+ "loang;": '\U000027EC',
+ "loarr;": '\U000021FD',
+ "lobrk;": '\U000027E6',
+ "longleftarrow;": '\U000027F5',
+ "longleftrightarrow;": '\U000027F7',
+ "longmapsto;": '\U000027FC',
+ "longrightarrow;": '\U000027F6',
+ "looparrowleft;": '\U000021AB',
+ "looparrowright;": '\U000021AC',
+ "lopar;": '\U00002985',
+ "lopf;": '\U0001D55D',
+ "loplus;": '\U00002A2D',
+ "lotimes;": '\U00002A34',
+ "lowast;": '\U00002217',
+ "lowbar;": '\U0000005F',
+ "loz;": '\U000025CA',
+ "lozenge;": '\U000025CA',
+ "lozf;": '\U000029EB',
+ "lpar;": '\U00000028',
+ "lparlt;": '\U00002993',
+ "lrarr;": '\U000021C6',
+ "lrcorner;": '\U0000231F',
+ "lrhar;": '\U000021CB',
+ "lrhard;": '\U0000296D',
+ "lrm;": '\U0000200E',
+ "lrtri;": '\U000022BF',
+ "lsaquo;": '\U00002039',
+ "lscr;": '\U0001D4C1',
+ "lsh;": '\U000021B0',
+ "lsim;": '\U00002272',
+ "lsime;": '\U00002A8D',
+ "lsimg;": '\U00002A8F',
+ "lsqb;": '\U0000005B',
+ "lsquo;": '\U00002018',
+ "lsquor;": '\U0000201A',
+ "lstrok;": '\U00000142',
+ "lt;": '\U0000003C',
+ "ltcc;": '\U00002AA6',
+ "ltcir;": '\U00002A79',
+ "ltdot;": '\U000022D6',
+ "lthree;": '\U000022CB',
+ "ltimes;": '\U000022C9',
+ "ltlarr;": '\U00002976',
+ "ltquest;": '\U00002A7B',
+ "ltrPar;": '\U00002996',
+ "ltri;": '\U000025C3',
+ "ltrie;": '\U000022B4',
+ "ltrif;": '\U000025C2',
+ "lurdshar;": '\U0000294A',
+ "luruhar;": '\U00002966',
+ "mDDot;": '\U0000223A',
+ "macr;": '\U000000AF',
+ "male;": '\U00002642',
+ "malt;": '\U00002720',
+ "maltese;": '\U00002720',
+ "map;": '\U000021A6',
+ "mapsto;": '\U000021A6',
+ "mapstodown;": '\U000021A7',
+ "mapstoleft;": '\U000021A4',
+ "mapstoup;": '\U000021A5',
+ "marker;": '\U000025AE',
+ "mcomma;": '\U00002A29',
+ "mcy;": '\U0000043C',
+ "mdash;": '\U00002014',
+ "measuredangle;": '\U00002221',
+ "mfr;": '\U0001D52A',
+ "mho;": '\U00002127',
+ "micro;": '\U000000B5',
+ "mid;": '\U00002223',
+ "midast;": '\U0000002A',
+ "midcir;": '\U00002AF0',
+ "middot;": '\U000000B7',
+ "minus;": '\U00002212',
+ "minusb;": '\U0000229F',
+ "minusd;": '\U00002238',
+ "minusdu;": '\U00002A2A',
+ "mlcp;": '\U00002ADB',
+ "mldr;": '\U00002026',
+ "mnplus;": '\U00002213',
+ "models;": '\U000022A7',
+ "mopf;": '\U0001D55E',
+ "mp;": '\U00002213',
+ "mscr;": '\U0001D4C2',
+ "mstpos;": '\U0000223E',
+ "mu;": '\U000003BC',
+ "multimap;": '\U000022B8',
+ "mumap;": '\U000022B8',
+ "nLeftarrow;": '\U000021CD',
+ "nLeftrightarrow;": '\U000021CE',
+ "nRightarrow;": '\U000021CF',
+ "nVDash;": '\U000022AF',
+ "nVdash;": '\U000022AE',
+ "nabla;": '\U00002207',
+ "nacute;": '\U00000144',
+ "nap;": '\U00002249',
+ "napos;": '\U00000149',
+ "napprox;": '\U00002249',
+ "natur;": '\U0000266E',
+ "natural;": '\U0000266E',
+ "naturals;": '\U00002115',
+ "nbsp;": '\U000000A0',
+ "ncap;": '\U00002A43',
+ "ncaron;": '\U00000148',
+ "ncedil;": '\U00000146',
+ "ncong;": '\U00002247',
+ "ncup;": '\U00002A42',
+ "ncy;": '\U0000043D',
+ "ndash;": '\U00002013',
+ "ne;": '\U00002260',
+ "neArr;": '\U000021D7',
+ "nearhk;": '\U00002924',
+ "nearr;": '\U00002197',
+ "nearrow;": '\U00002197',
+ "nequiv;": '\U00002262',
+ "nesear;": '\U00002928',
+ "nexist;": '\U00002204',
+ "nexists;": '\U00002204',
+ "nfr;": '\U0001D52B',
+ "nge;": '\U00002271',
+ "ngeq;": '\U00002271',
+ "ngsim;": '\U00002275',
+ "ngt;": '\U0000226F',
+ "ngtr;": '\U0000226F',
+ "nhArr;": '\U000021CE',
+ "nharr;": '\U000021AE',
+ "nhpar;": '\U00002AF2',
+ "ni;": '\U0000220B',
+ "nis;": '\U000022FC',
+ "nisd;": '\U000022FA',
+ "niv;": '\U0000220B',
+ "njcy;": '\U0000045A',
+ "nlArr;": '\U000021CD',
+ "nlarr;": '\U0000219A',
+ "nldr;": '\U00002025',
+ "nle;": '\U00002270',
+ "nleftarrow;": '\U0000219A',
+ "nleftrightarrow;": '\U000021AE',
+ "nleq;": '\U00002270',
+ "nless;": '\U0000226E',
+ "nlsim;": '\U00002274',
+ "nlt;": '\U0000226E',
+ "nltri;": '\U000022EA',
+ "nltrie;": '\U000022EC',
+ "nmid;": '\U00002224',
+ "nopf;": '\U0001D55F',
+ "not;": '\U000000AC',
+ "notin;": '\U00002209',
+ "notinva;": '\U00002209',
+ "notinvb;": '\U000022F7',
+ "notinvc;": '\U000022F6',
+ "notni;": '\U0000220C',
+ "notniva;": '\U0000220C',
+ "notnivb;": '\U000022FE',
+ "notnivc;": '\U000022FD',
+ "npar;": '\U00002226',
+ "nparallel;": '\U00002226',
+ "npolint;": '\U00002A14',
+ "npr;": '\U00002280',
+ "nprcue;": '\U000022E0',
+ "nprec;": '\U00002280',
+ "nrArr;": '\U000021CF',
+ "nrarr;": '\U0000219B',
+ "nrightarrow;": '\U0000219B',
+ "nrtri;": '\U000022EB',
+ "nrtrie;": '\U000022ED',
+ "nsc;": '\U00002281',
+ "nsccue;": '\U000022E1',
+ "nscr;": '\U0001D4C3',
+ "nshortmid;": '\U00002224',
+ "nshortparallel;": '\U00002226',
+ "nsim;": '\U00002241',
+ "nsime;": '\U00002244',
+ "nsimeq;": '\U00002244',
+ "nsmid;": '\U00002224',
+ "nspar;": '\U00002226',
+ "nsqsube;": '\U000022E2',
+ "nsqsupe;": '\U000022E3',
+ "nsub;": '\U00002284',
+ "nsube;": '\U00002288',
+ "nsubseteq;": '\U00002288',
+ "nsucc;": '\U00002281',
+ "nsup;": '\U00002285',
+ "nsupe;": '\U00002289',
+ "nsupseteq;": '\U00002289',
+ "ntgl;": '\U00002279',
+ "ntilde;": '\U000000F1',
+ "ntlg;": '\U00002278',
+ "ntriangleleft;": '\U000022EA',
+ "ntrianglelefteq;": '\U000022EC',
+ "ntriangleright;": '\U000022EB',
+ "ntrianglerighteq;": '\U000022ED',
+ "nu;": '\U000003BD',
+ "num;": '\U00000023',
+ "numero;": '\U00002116',
+ "numsp;": '\U00002007',
+ "nvDash;": '\U000022AD',
+ "nvHarr;": '\U00002904',
+ "nvdash;": '\U000022AC',
+ "nvinfin;": '\U000029DE',
+ "nvlArr;": '\U00002902',
+ "nvrArr;": '\U00002903',
+ "nwArr;": '\U000021D6',
+ "nwarhk;": '\U00002923',
+ "nwarr;": '\U00002196',
+ "nwarrow;": '\U00002196',
+ "nwnear;": '\U00002927',
+ "oS;": '\U000024C8',
+ "oacute;": '\U000000F3',
+ "oast;": '\U0000229B',
+ "ocir;": '\U0000229A',
+ "ocirc;": '\U000000F4',
+ "ocy;": '\U0000043E',
+ "odash;": '\U0000229D',
+ "odblac;": '\U00000151',
+ "odiv;": '\U00002A38',
+ "odot;": '\U00002299',
+ "odsold;": '\U000029BC',
+ "oelig;": '\U00000153',
+ "ofcir;": '\U000029BF',
+ "ofr;": '\U0001D52C',
+ "ogon;": '\U000002DB',
+ "ograve;": '\U000000F2',
+ "ogt;": '\U000029C1',
+ "ohbar;": '\U000029B5',
+ "ohm;": '\U000003A9',
+ "oint;": '\U0000222E',
+ "olarr;": '\U000021BA',
+ "olcir;": '\U000029BE',
+ "olcross;": '\U000029BB',
+ "oline;": '\U0000203E',
+ "olt;": '\U000029C0',
+ "omacr;": '\U0000014D',
+ "omega;": '\U000003C9',
+ "omicron;": '\U000003BF',
+ "omid;": '\U000029B6',
+ "ominus;": '\U00002296',
+ "oopf;": '\U0001D560',
+ "opar;": '\U000029B7',
+ "operp;": '\U000029B9',
+ "oplus;": '\U00002295',
+ "or;": '\U00002228',
+ "orarr;": '\U000021BB',
+ "ord;": '\U00002A5D',
+ "order;": '\U00002134',
+ "orderof;": '\U00002134',
+ "ordf;": '\U000000AA',
+ "ordm;": '\U000000BA',
+ "origof;": '\U000022B6',
+ "oror;": '\U00002A56',
+ "orslope;": '\U00002A57',
+ "orv;": '\U00002A5B',
+ "oscr;": '\U00002134',
+ "oslash;": '\U000000F8',
+ "osol;": '\U00002298',
+ "otilde;": '\U000000F5',
+ "otimes;": '\U00002297',
+ "otimesas;": '\U00002A36',
+ "ouml;": '\U000000F6',
+ "ovbar;": '\U0000233D',
+ "par;": '\U00002225',
+ "para;": '\U000000B6',
+ "parallel;": '\U00002225',
+ "parsim;": '\U00002AF3',
+ "parsl;": '\U00002AFD',
+ "part;": '\U00002202',
+ "pcy;": '\U0000043F',
+ "percnt;": '\U00000025',
+ "period;": '\U0000002E',
+ "permil;": '\U00002030',
+ "perp;": '\U000022A5',
+ "pertenk;": '\U00002031',
+ "pfr;": '\U0001D52D',
+ "phi;": '\U000003C6',
+ "phiv;": '\U000003D5',
+ "phmmat;": '\U00002133',
+ "phone;": '\U0000260E',
+ "pi;": '\U000003C0',
+ "pitchfork;": '\U000022D4',
+ "piv;": '\U000003D6',
+ "planck;": '\U0000210F',
+ "planckh;": '\U0000210E',
+ "plankv;": '\U0000210F',
+ "plus;": '\U0000002B',
+ "plusacir;": '\U00002A23',
+ "plusb;": '\U0000229E',
+ "pluscir;": '\U00002A22',
+ "plusdo;": '\U00002214',
+ "plusdu;": '\U00002A25',
+ "pluse;": '\U00002A72',
+ "plusmn;": '\U000000B1',
+ "plussim;": '\U00002A26',
+ "plustwo;": '\U00002A27',
+ "pm;": '\U000000B1',
+ "pointint;": '\U00002A15',
+ "popf;": '\U0001D561',
+ "pound;": '\U000000A3',
+ "pr;": '\U0000227A',
+ "prE;": '\U00002AB3',
+ "prap;": '\U00002AB7',
+ "prcue;": '\U0000227C',
+ "pre;": '\U00002AAF',
+ "prec;": '\U0000227A',
+ "precapprox;": '\U00002AB7',
+ "preccurlyeq;": '\U0000227C',
+ "preceq;": '\U00002AAF',
+ "precnapprox;": '\U00002AB9',
+ "precneqq;": '\U00002AB5',
+ "precnsim;": '\U000022E8',
+ "precsim;": '\U0000227E',
+ "prime;": '\U00002032',
+ "primes;": '\U00002119',
+ "prnE;": '\U00002AB5',
+ "prnap;": '\U00002AB9',
+ "prnsim;": '\U000022E8',
+ "prod;": '\U0000220F',
+ "profalar;": '\U0000232E',
+ "profline;": '\U00002312',
+ "profsurf;": '\U00002313',
+ "prop;": '\U0000221D',
+ "propto;": '\U0000221D',
+ "prsim;": '\U0000227E',
+ "prurel;": '\U000022B0',
+ "pscr;": '\U0001D4C5',
+ "psi;": '\U000003C8',
+ "puncsp;": '\U00002008',
+ "qfr;": '\U0001D52E',
+ "qint;": '\U00002A0C',
+ "qopf;": '\U0001D562',
+ "qprime;": '\U00002057',
+ "qscr;": '\U0001D4C6',
+ "quaternions;": '\U0000210D',
+ "quatint;": '\U00002A16',
+ "quest;": '\U0000003F',
+ "questeq;": '\U0000225F',
+ "quot;": '\U00000022',
+ "rAarr;": '\U000021DB',
+ "rArr;": '\U000021D2',
+ "rAtail;": '\U0000291C',
+ "rBarr;": '\U0000290F',
+ "rHar;": '\U00002964',
+ "racute;": '\U00000155',
+ "radic;": '\U0000221A',
+ "raemptyv;": '\U000029B3',
+ "rang;": '\U000027E9',
+ "rangd;": '\U00002992',
+ "range;": '\U000029A5',
+ "rangle;": '\U000027E9',
+ "raquo;": '\U000000BB',
+ "rarr;": '\U00002192',
+ "rarrap;": '\U00002975',
+ "rarrb;": '\U000021E5',
+ "rarrbfs;": '\U00002920',
+ "rarrc;": '\U00002933',
+ "rarrfs;": '\U0000291E',
+ "rarrhk;": '\U000021AA',
+ "rarrlp;": '\U000021AC',
+ "rarrpl;": '\U00002945',
+ "rarrsim;": '\U00002974',
+ "rarrtl;": '\U000021A3',
+ "rarrw;": '\U0000219D',
+ "ratail;": '\U0000291A',
+ "ratio;": '\U00002236',
+ "rationals;": '\U0000211A',
+ "rbarr;": '\U0000290D',
+ "rbbrk;": '\U00002773',
+ "rbrace;": '\U0000007D',
+ "rbrack;": '\U0000005D',
+ "rbrke;": '\U0000298C',
+ "rbrksld;": '\U0000298E',
+ "rbrkslu;": '\U00002990',
+ "rcaron;": '\U00000159',
+ "rcedil;": '\U00000157',
+ "rceil;": '\U00002309',
+ "rcub;": '\U0000007D',
+ "rcy;": '\U00000440',
+ "rdca;": '\U00002937',
+ "rdldhar;": '\U00002969',
+ "rdquo;": '\U0000201D',
+ "rdquor;": '\U0000201D',
+ "rdsh;": '\U000021B3',
+ "real;": '\U0000211C',
+ "realine;": '\U0000211B',
+ "realpart;": '\U0000211C',
+ "reals;": '\U0000211D',
+ "rect;": '\U000025AD',
+ "reg;": '\U000000AE',
+ "rfisht;": '\U0000297D',
+ "rfloor;": '\U0000230B',
+ "rfr;": '\U0001D52F',
+ "rhard;": '\U000021C1',
+ "rharu;": '\U000021C0',
+ "rharul;": '\U0000296C',
+ "rho;": '\U000003C1',
+ "rhov;": '\U000003F1',
+ "rightarrow;": '\U00002192',
+ "rightarrowtail;": '\U000021A3',
+ "rightharpoondown;": '\U000021C1',
+ "rightharpoonup;": '\U000021C0',
+ "rightleftarrows;": '\U000021C4',
+ "rightleftharpoons;": '\U000021CC',
+ "rightrightarrows;": '\U000021C9',
+ "rightsquigarrow;": '\U0000219D',
+ "rightthreetimes;": '\U000022CC',
+ "ring;": '\U000002DA',
+ "risingdotseq;": '\U00002253',
+ "rlarr;": '\U000021C4',
+ "rlhar;": '\U000021CC',
+ "rlm;": '\U0000200F',
+ "rmoust;": '\U000023B1',
+ "rmoustache;": '\U000023B1',
+ "rnmid;": '\U00002AEE',
+ "roang;": '\U000027ED',
+ "roarr;": '\U000021FE',
+ "robrk;": '\U000027E7',
+ "ropar;": '\U00002986',
+ "ropf;": '\U0001D563',
+ "roplus;": '\U00002A2E',
+ "rotimes;": '\U00002A35',
+ "rpar;": '\U00000029',
+ "rpargt;": '\U00002994',
+ "rppolint;": '\U00002A12',
+ "rrarr;": '\U000021C9',
+ "rsaquo;": '\U0000203A',
+ "rscr;": '\U0001D4C7',
+ "rsh;": '\U000021B1',
+ "rsqb;": '\U0000005D',
+ "rsquo;": '\U00002019',
+ "rsquor;": '\U00002019',
+ "rthree;": '\U000022CC',
+ "rtimes;": '\U000022CA',
+ "rtri;": '\U000025B9',
+ "rtrie;": '\U000022B5',
+ "rtrif;": '\U000025B8',
+ "rtriltri;": '\U000029CE',
+ "ruluhar;": '\U00002968',
+ "rx;": '\U0000211E',
+ "sacute;": '\U0000015B',
+ "sbquo;": '\U0000201A',
+ "sc;": '\U0000227B',
+ "scE;": '\U00002AB4',
+ "scap;": '\U00002AB8',
+ "scaron;": '\U00000161',
+ "sccue;": '\U0000227D',
+ "sce;": '\U00002AB0',
+ "scedil;": '\U0000015F',
+ "scirc;": '\U0000015D',
+ "scnE;": '\U00002AB6',
+ "scnap;": '\U00002ABA',
+ "scnsim;": '\U000022E9',
+ "scpolint;": '\U00002A13',
+ "scsim;": '\U0000227F',
+ "scy;": '\U00000441',
+ "sdot;": '\U000022C5',
+ "sdotb;": '\U000022A1',
+ "sdote;": '\U00002A66',
+ "seArr;": '\U000021D8',
+ "searhk;": '\U00002925',
+ "searr;": '\U00002198',
+ "searrow;": '\U00002198',
+ "sect;": '\U000000A7',
+ "semi;": '\U0000003B',
+ "seswar;": '\U00002929',
+ "setminus;": '\U00002216',
+ "setmn;": '\U00002216',
+ "sext;": '\U00002736',
+ "sfr;": '\U0001D530',
+ "sfrown;": '\U00002322',
+ "sharp;": '\U0000266F',
+ "shchcy;": '\U00000449',
+ "shcy;": '\U00000448',
+ "shortmid;": '\U00002223',
+ "shortparallel;": '\U00002225',
+ "shy;": '\U000000AD',
+ "sigma;": '\U000003C3',
+ "sigmaf;": '\U000003C2',
+ "sigmav;": '\U000003C2',
+ "sim;": '\U0000223C',
+ "simdot;": '\U00002A6A',
+ "sime;": '\U00002243',
+ "simeq;": '\U00002243',
+ "simg;": '\U00002A9E',
+ "simgE;": '\U00002AA0',
+ "siml;": '\U00002A9D',
+ "simlE;": '\U00002A9F',
+ "simne;": '\U00002246',
+ "simplus;": '\U00002A24',
+ "simrarr;": '\U00002972',
+ "slarr;": '\U00002190',
+ "smallsetminus;": '\U00002216',
+ "smashp;": '\U00002A33',
+ "smeparsl;": '\U000029E4',
+ "smid;": '\U00002223',
+ "smile;": '\U00002323',
+ "smt;": '\U00002AAA',
+ "smte;": '\U00002AAC',
+ "softcy;": '\U0000044C',
+ "sol;": '\U0000002F',
+ "solb;": '\U000029C4',
+ "solbar;": '\U0000233F',
+ "sopf;": '\U0001D564',
+ "spades;": '\U00002660',
+ "spadesuit;": '\U00002660',
+ "spar;": '\U00002225',
+ "sqcap;": '\U00002293',
+ "sqcup;": '\U00002294',
+ "sqsub;": '\U0000228F',
+ "sqsube;": '\U00002291',
+ "sqsubset;": '\U0000228F',
+ "sqsubseteq;": '\U00002291',
+ "sqsup;": '\U00002290',
+ "sqsupe;": '\U00002292',
+ "sqsupset;": '\U00002290',
+ "sqsupseteq;": '\U00002292',
+ "squ;": '\U000025A1',
+ "square;": '\U000025A1',
+ "squarf;": '\U000025AA',
+ "squf;": '\U000025AA',
+ "srarr;": '\U00002192',
+ "sscr;": '\U0001D4C8',
+ "ssetmn;": '\U00002216',
+ "ssmile;": '\U00002323',
+ "sstarf;": '\U000022C6',
+ "star;": '\U00002606',
+ "starf;": '\U00002605',
+ "straightepsilon;": '\U000003F5',
+ "straightphi;": '\U000003D5',
+ "strns;": '\U000000AF',
+ "sub;": '\U00002282',
+ "subE;": '\U00002AC5',
+ "subdot;": '\U00002ABD',
+ "sube;": '\U00002286',
+ "subedot;": '\U00002AC3',
+ "submult;": '\U00002AC1',
+ "subnE;": '\U00002ACB',
+ "subne;": '\U0000228A',
+ "subplus;": '\U00002ABF',
+ "subrarr;": '\U00002979',
+ "subset;": '\U00002282',
+ "subseteq;": '\U00002286',
+ "subseteqq;": '\U00002AC5',
+ "subsetneq;": '\U0000228A',
+ "subsetneqq;": '\U00002ACB',
+ "subsim;": '\U00002AC7',
+ "subsub;": '\U00002AD5',
+ "subsup;": '\U00002AD3',
+ "succ;": '\U0000227B',
+ "succapprox;": '\U00002AB8',
+ "succcurlyeq;": '\U0000227D',
+ "succeq;": '\U00002AB0',
+ "succnapprox;": '\U00002ABA',
+ "succneqq;": '\U00002AB6',
+ "succnsim;": '\U000022E9',
+ "succsim;": '\U0000227F',
+ "sum;": '\U00002211',
+ "sung;": '\U0000266A',
+ "sup;": '\U00002283',
+ "sup1;": '\U000000B9',
+ "sup2;": '\U000000B2',
+ "sup3;": '\U000000B3',
+ "supE;": '\U00002AC6',
+ "supdot;": '\U00002ABE',
+ "supdsub;": '\U00002AD8',
+ "supe;": '\U00002287',
+ "supedot;": '\U00002AC4',
+ "suphsol;": '\U000027C9',
+ "suphsub;": '\U00002AD7',
+ "suplarr;": '\U0000297B',
+ "supmult;": '\U00002AC2',
+ "supnE;": '\U00002ACC',
+ "supne;": '\U0000228B',
+ "supplus;": '\U00002AC0',
+ "supset;": '\U00002283',
+ "supseteq;": '\U00002287',
+ "supseteqq;": '\U00002AC6',
+ "supsetneq;": '\U0000228B',
+ "supsetneqq;": '\U00002ACC',
+ "supsim;": '\U00002AC8',
+ "supsub;": '\U00002AD4',
+ "supsup;": '\U00002AD6',
+ "swArr;": '\U000021D9',
+ "swarhk;": '\U00002926',
+ "swarr;": '\U00002199',
+ "swarrow;": '\U00002199',
+ "swnwar;": '\U0000292A',
+ "szlig;": '\U000000DF',
+ "target;": '\U00002316',
+ "tau;": '\U000003C4',
+ "tbrk;": '\U000023B4',
+ "tcaron;": '\U00000165',
+ "tcedil;": '\U00000163',
+ "tcy;": '\U00000442',
+ "tdot;": '\U000020DB',
+ "telrec;": '\U00002315',
+ "tfr;": '\U0001D531',
+ "there4;": '\U00002234',
+ "therefore;": '\U00002234',
+ "theta;": '\U000003B8',
+ "thetasym;": '\U000003D1',
+ "thetav;": '\U000003D1',
+ "thickapprox;": '\U00002248',
+ "thicksim;": '\U0000223C',
+ "thinsp;": '\U00002009',
+ "thkap;": '\U00002248',
+ "thksim;": '\U0000223C',
+ "thorn;": '\U000000FE',
+ "tilde;": '\U000002DC',
+ "times;": '\U000000D7',
+ "timesb;": '\U000022A0',
+ "timesbar;": '\U00002A31',
+ "timesd;": '\U00002A30',
+ "tint;": '\U0000222D',
+ "toea;": '\U00002928',
+ "top;": '\U000022A4',
+ "topbot;": '\U00002336',
+ "topcir;": '\U00002AF1',
+ "topf;": '\U0001D565',
+ "topfork;": '\U00002ADA',
+ "tosa;": '\U00002929',
+ "tprime;": '\U00002034',
+ "trade;": '\U00002122',
+ "triangle;": '\U000025B5',
+ "triangledown;": '\U000025BF',
+ "triangleleft;": '\U000025C3',
+ "trianglelefteq;": '\U000022B4',
+ "triangleq;": '\U0000225C',
+ "triangleright;": '\U000025B9',
+ "trianglerighteq;": '\U000022B5',
+ "tridot;": '\U000025EC',
+ "trie;": '\U0000225C',
+ "triminus;": '\U00002A3A',
+ "triplus;": '\U00002A39',
+ "trisb;": '\U000029CD',
+ "tritime;": '\U00002A3B',
+ "trpezium;": '\U000023E2',
+ "tscr;": '\U0001D4C9',
+ "tscy;": '\U00000446',
+ "tshcy;": '\U0000045B',
+ "tstrok;": '\U00000167',
+ "twixt;": '\U0000226C',
+ "twoheadleftarrow;": '\U0000219E',
+ "twoheadrightarrow;": '\U000021A0',
+ "uArr;": '\U000021D1',
+ "uHar;": '\U00002963',
+ "uacute;": '\U000000FA',
+ "uarr;": '\U00002191',
+ "ubrcy;": '\U0000045E',
+ "ubreve;": '\U0000016D',
+ "ucirc;": '\U000000FB',
+ "ucy;": '\U00000443',
+ "udarr;": '\U000021C5',
+ "udblac;": '\U00000171',
+ "udhar;": '\U0000296E',
+ "ufisht;": '\U0000297E',
+ "ufr;": '\U0001D532',
+ "ugrave;": '\U000000F9',
+ "uharl;": '\U000021BF',
+ "uharr;": '\U000021BE',
+ "uhblk;": '\U00002580',
+ "ulcorn;": '\U0000231C',
+ "ulcorner;": '\U0000231C',
+ "ulcrop;": '\U0000230F',
+ "ultri;": '\U000025F8',
+ "umacr;": '\U0000016B',
+ "uml;": '\U000000A8',
+ "uogon;": '\U00000173',
+ "uopf;": '\U0001D566',
+ "uparrow;": '\U00002191',
+ "updownarrow;": '\U00002195',
+ "upharpoonleft;": '\U000021BF',
+ "upharpoonright;": '\U000021BE',
+ "uplus;": '\U0000228E',
+ "upsi;": '\U000003C5',
+ "upsih;": '\U000003D2',
+ "upsilon;": '\U000003C5',
+ "upuparrows;": '\U000021C8',
+ "urcorn;": '\U0000231D',
+ "urcorner;": '\U0000231D',
+ "urcrop;": '\U0000230E',
+ "uring;": '\U0000016F',
+ "urtri;": '\U000025F9',
+ "uscr;": '\U0001D4CA',
+ "utdot;": '\U000022F0',
+ "utilde;": '\U00000169',
+ "utri;": '\U000025B5',
+ "utrif;": '\U000025B4',
+ "uuarr;": '\U000021C8',
+ "uuml;": '\U000000FC',
+ "uwangle;": '\U000029A7',
+ "vArr;": '\U000021D5',
+ "vBar;": '\U00002AE8',
+ "vBarv;": '\U00002AE9',
+ "vDash;": '\U000022A8',
+ "vangrt;": '\U0000299C',
+ "varepsilon;": '\U000003F5',
+ "varkappa;": '\U000003F0',
+ "varnothing;": '\U00002205',
+ "varphi;": '\U000003D5',
+ "varpi;": '\U000003D6',
+ "varpropto;": '\U0000221D',
+ "varr;": '\U00002195',
+ "varrho;": '\U000003F1',
+ "varsigma;": '\U000003C2',
+ "vartheta;": '\U000003D1',
+ "vartriangleleft;": '\U000022B2',
+ "vartriangleright;": '\U000022B3',
+ "vcy;": '\U00000432',
+ "vdash;": '\U000022A2',
+ "vee;": '\U00002228',
+ "veebar;": '\U000022BB',
+ "veeeq;": '\U0000225A',
+ "vellip;": '\U000022EE',
+ "verbar;": '\U0000007C',
+ "vert;": '\U0000007C',
+ "vfr;": '\U0001D533',
+ "vltri;": '\U000022B2',
+ "vopf;": '\U0001D567',
+ "vprop;": '\U0000221D',
+ "vrtri;": '\U000022B3',
+ "vscr;": '\U0001D4CB',
+ "vzigzag;": '\U0000299A',
+ "wcirc;": '\U00000175',
+ "wedbar;": '\U00002A5F',
+ "wedge;": '\U00002227',
+ "wedgeq;": '\U00002259',
+ "weierp;": '\U00002118',
+ "wfr;": '\U0001D534',
+ "wopf;": '\U0001D568',
+ "wp;": '\U00002118',
+ "wr;": '\U00002240',
+ "wreath;": '\U00002240',
+ "wscr;": '\U0001D4CC',
+ "xcap;": '\U000022C2',
+ "xcirc;": '\U000025EF',
+ "xcup;": '\U000022C3',
+ "xdtri;": '\U000025BD',
+ "xfr;": '\U0001D535',
+ "xhArr;": '\U000027FA',
+ "xharr;": '\U000027F7',
+ "xi;": '\U000003BE',
+ "xlArr;": '\U000027F8',
+ "xlarr;": '\U000027F5',
+ "xmap;": '\U000027FC',
+ "xnis;": '\U000022FB',
+ "xodot;": '\U00002A00',
+ "xopf;": '\U0001D569',
+ "xoplus;": '\U00002A01',
+ "xotime;": '\U00002A02',
+ "xrArr;": '\U000027F9',
+ "xrarr;": '\U000027F6',
+ "xscr;": '\U0001D4CD',
+ "xsqcup;": '\U00002A06',
+ "xuplus;": '\U00002A04',
+ "xutri;": '\U000025B3',
+ "xvee;": '\U000022C1',
+ "xwedge;": '\U000022C0',
+ "yacute;": '\U000000FD',
+ "yacy;": '\U0000044F',
+ "ycirc;": '\U00000177',
+ "ycy;": '\U0000044B',
+ "yen;": '\U000000A5',
+ "yfr;": '\U0001D536',
+ "yicy;": '\U00000457',
+ "yopf;": '\U0001D56A',
+ "yscr;": '\U0001D4CE',
+ "yucy;": '\U0000044E',
+ "yuml;": '\U000000FF',
+ "zacute;": '\U0000017A',
+ "zcaron;": '\U0000017E',
+ "zcy;": '\U00000437',
+ "zdot;": '\U0000017C',
+ "zeetrf;": '\U00002128',
+ "zeta;": '\U000003B6',
+ "zfr;": '\U0001D537',
+ "zhcy;": '\U00000436',
+ "zigrarr;": '\U000021DD',
+ "zopf;": '\U0001D56B',
+ "zscr;": '\U0001D4CF',
+ "zwj;": '\U0000200D',
+ "zwnj;": '\U0000200C',
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Acirc": '\U000000C2',
+ "Agrave": '\U000000C0',
+ "Aring": '\U000000C5',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "COPY": '\U000000A9',
+ "Ccedil": '\U000000C7',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecirc": '\U000000CA',
+ "Egrave": '\U000000C8',
+ "Euml": '\U000000CB',
+ "GT": '\U0000003E',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Igrave": '\U000000CC',
+ "Iuml": '\U000000CF',
+ "LT": '\U0000003C',
+ "Ntilde": '\U000000D1',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ograve": '\U000000D2',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Ouml": '\U000000D6',
+ "QUOT": '\U00000022',
+ "REG": '\U000000AE',
+ "THORN": '\U000000DE',
+ "Uacute": '\U000000DA',
+ "Ucirc": '\U000000DB',
+ "Ugrave": '\U000000D9',
+ "Uuml": '\U000000DC',
+ "Yacute": '\U000000DD',
+ "aacute": '\U000000E1',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "aelig": '\U000000E6',
+ "agrave": '\U000000E0',
+ "amp": '\U00000026',
+ "aring": '\U000000E5',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "brvbar": '\U000000A6',
+ "ccedil": '\U000000E7',
+ "cedil": '\U000000B8',
+ "cent": '\U000000A2',
+ "copy": '\U000000A9',
+ "curren": '\U000000A4',
+ "deg": '\U000000B0',
+ "divide": '\U000000F7',
+ "eacute": '\U000000E9',
+ "ecirc": '\U000000EA',
+ "egrave": '\U000000E8',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "frac12": '\U000000BD',
+ "frac14": '\U000000BC',
+ "frac34": '\U000000BE',
+ "gt": '\U0000003E',
+ "iacute": '\U000000ED',
+ "icirc": '\U000000EE',
+ "iexcl": '\U000000A1',
+ "igrave": '\U000000EC',
+ "iquest": '\U000000BF',
+ "iuml": '\U000000EF',
+ "laquo": '\U000000AB',
+ "lt": '\U0000003C',
+ "macr": '\U000000AF',
+ "micro": '\U000000B5',
+ "middot": '\U000000B7',
+ "nbsp": '\U000000A0',
+ "not": '\U000000AC',
+ "ntilde": '\U000000F1',
+ "oacute": '\U000000F3',
+ "ocirc": '\U000000F4',
+ "ograve": '\U000000F2',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "oslash": '\U000000F8',
+ "otilde": '\U000000F5',
+ "ouml": '\U000000F6',
+ "para": '\U000000B6',
+ "plusmn": '\U000000B1',
+ "pound": '\U000000A3',
+ "quot": '\U00000022',
+ "raquo": '\U000000BB',
+ "reg": '\U000000AE',
+ "sect": '\U000000A7',
+ "shy": '\U000000AD',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "szlig": '\U000000DF',
+ "thorn": '\U000000FE',
+ "times": '\U000000D7',
+ "uacute": '\U000000FA',
+ "ucirc": '\U000000FB',
+ "ugrave": '\U000000F9',
+ "uml": '\U000000A8',
+ "uuml": '\U000000FC',
+ "yacute": '\U000000FD',
+ "yen": '\U000000A5',
+ "yuml": '\U000000FF',
+}
+
+// HTML entities that are two unicode codepoints.
+var entity2 = map[string][2]rune{
+ // TODO(nigeltao): Handle replacements that are wider than their names.
+ // "nLt;": {'\u226A', '\u20D2'},
+ // "nGt;": {'\u226B', '\u20D2'},
+ "NotEqualTilde;": {'\u2242', '\u0338'},
+ "NotGreaterFullEqual;": {'\u2267', '\u0338'},
+ "NotGreaterGreater;": {'\u226B', '\u0338'},
+ "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'},
+ "NotHumpDownHump;": {'\u224E', '\u0338'},
+ "NotHumpEqual;": {'\u224F', '\u0338'},
+ "NotLeftTriangleBar;": {'\u29CF', '\u0338'},
+ "NotLessLess;": {'\u226A', '\u0338'},
+ "NotLessSlantEqual;": {'\u2A7D', '\u0338'},
+ "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+ "NotNestedLessLess;": {'\u2AA1', '\u0338'},
+ "NotPrecedesEqual;": {'\u2AAF', '\u0338'},
+ "NotRightTriangleBar;": {'\u29D0', '\u0338'},
+ "NotSquareSubset;": {'\u228F', '\u0338'},
+ "NotSquareSuperset;": {'\u2290', '\u0338'},
+ "NotSubset;": {'\u2282', '\u20D2'},
+ "NotSucceedsEqual;": {'\u2AB0', '\u0338'},
+ "NotSucceedsTilde;": {'\u227F', '\u0338'},
+ "NotSuperset;": {'\u2283', '\u20D2'},
+ "ThickSpace;": {'\u205F', '\u200A'},
+ "acE;": {'\u223E', '\u0333'},
+ "bne;": {'\u003D', '\u20E5'},
+ "bnequiv;": {'\u2261', '\u20E5'},
+ "caps;": {'\u2229', '\uFE00'},
+ "cups;": {'\u222A', '\uFE00'},
+ "fjlig;": {'\u0066', '\u006A'},
+ "gesl;": {'\u22DB', '\uFE00'},
+ "gvertneqq;": {'\u2269', '\uFE00'},
+ "gvnE;": {'\u2269', '\uFE00'},
+ "lates;": {'\u2AAD', '\uFE00'},
+ "lesg;": {'\u22DA', '\uFE00'},
+ "lvertneqq;": {'\u2268', '\uFE00'},
+ "lvnE;": {'\u2268', '\uFE00'},
+ "nGg;": {'\u22D9', '\u0338'},
+ "nGtv;": {'\u226B', '\u0338'},
+ "nLl;": {'\u22D8', '\u0338'},
+ "nLtv;": {'\u226A', '\u0338'},
+ "nang;": {'\u2220', '\u20D2'},
+ "napE;": {'\u2A70', '\u0338'},
+ "napid;": {'\u224B', '\u0338'},
+ "nbump;": {'\u224E', '\u0338'},
+ "nbumpe;": {'\u224F', '\u0338'},
+ "ncongdot;": {'\u2A6D', '\u0338'},
+ "nedot;": {'\u2250', '\u0338'},
+ "nesim;": {'\u2242', '\u0338'},
+ "ngE;": {'\u2267', '\u0338'},
+ "ngeqq;": {'\u2267', '\u0338'},
+ "ngeqslant;": {'\u2A7E', '\u0338'},
+ "nges;": {'\u2A7E', '\u0338'},
+ "nlE;": {'\u2266', '\u0338'},
+ "nleqq;": {'\u2266', '\u0338'},
+ "nleqslant;": {'\u2A7D', '\u0338'},
+ "nles;": {'\u2A7D', '\u0338'},
+ "notinE;": {'\u22F9', '\u0338'},
+ "notindot;": {'\u22F5', '\u0338'},
+ "nparsl;": {'\u2AFD', '\u20E5'},
+ "npart;": {'\u2202', '\u0338'},
+ "npre;": {'\u2AAF', '\u0338'},
+ "npreceq;": {'\u2AAF', '\u0338'},
+ "nrarrc;": {'\u2933', '\u0338'},
+ "nrarrw;": {'\u219D', '\u0338'},
+ "nsce;": {'\u2AB0', '\u0338'},
+ "nsubE;": {'\u2AC5', '\u0338'},
+ "nsubset;": {'\u2282', '\u20D2'},
+ "nsubseteqq;": {'\u2AC5', '\u0338'},
+ "nsucceq;": {'\u2AB0', '\u0338'},
+ "nsupE;": {'\u2AC6', '\u0338'},
+ "nsupset;": {'\u2283', '\u20D2'},
+ "nsupseteqq;": {'\u2AC6', '\u0338'},
+ "nvap;": {'\u224D', '\u20D2'},
+ "nvge;": {'\u2265', '\u20D2'},
+ "nvgt;": {'\u003E', '\u20D2'},
+ "nvle;": {'\u2264', '\u20D2'},
+ "nvlt;": {'\u003C', '\u20D2'},
+ "nvltrie;": {'\u22B4', '\u20D2'},
+ "nvrtrie;": {'\u22B5', '\u20D2'},
+ "nvsim;": {'\u223C', '\u20D2'},
+ "race;": {'\u223D', '\u0331'},
+ "smtes;": {'\u2AAC', '\uFE00'},
+ "sqcaps;": {'\u2293', '\uFE00'},
+ "sqcups;": {'\u2294', '\uFE00'},
+ "varsubsetneq;": {'\u228A', '\uFE00'},
+ "varsubsetneqq;": {'\u2ACB', '\uFE00'},
+ "varsupsetneq;": {'\u228B', '\uFE00'},
+ "varsupsetneqq;": {'\u2ACC', '\uFE00'},
+ "vnsub;": {'\u2282', '\u20D2'},
+ "vnsup;": {'\u2283', '\u20D2'},
+ "vsubnE;": {'\u2ACB', '\uFE00'},
+ "vsubne;": {'\u228A', '\uFE00'},
+ "vsupnE;": {'\u2ACC', '\uFE00'},
+ "vsupne;": {'\u228B', '\uFE00'},
+}
diff --git a/libgo/go/exp/html/entity_test.go b/libgo/go/exp/html/entity_test.go
new file mode 100644
index 00000000000..b53f866fa2d
--- /dev/null
+++ b/libgo/go/exp/html/entity_test.go
@@ -0,0 +1,29 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "testing"
+ "unicode/utf8"
+)
+
+func TestEntityLength(t *testing.T) {
+ // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
+ // The +1 comes from the leading "&". This property implies that the length of
+ // unescaped text is <= the length of escaped text.
+ for k, v := range entity {
+ if 1+len(k) < utf8.RuneLen(v) {
+ t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
+ }
+ if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' {
+ t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon)
+ }
+ }
+ for k, v := range entity2 {
+ if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
+ t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
+ }
+ }
+}
diff --git a/libgo/go/exp/html/escape.go b/libgo/go/exp/html/escape.go
new file mode 100644
index 00000000000..42be865ef08
--- /dev/null
+++ b/libgo/go/exp/html/escape.go
@@ -0,0 +1,253 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "strings"
+ "unicode/utf8"
+)
+
+// These replacements permit compatibility with old numeric entities that
+// assumed Windows-1252 encoding.
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+var replacementTable = [...]rune{
+ '\u20AC', // First entry is what 0x80 should be replaced with.
+ '\u0081',
+ '\u201A',
+ '\u0192',
+ '\u201E',
+ '\u2026',
+ '\u2020',
+ '\u2021',
+ '\u02C6',
+ '\u2030',
+ '\u0160',
+ '\u2039',
+ '\u0152',
+ '\u008D',
+ '\u017D',
+ '\u008F',
+ '\u0090',
+ '\u2018',
+ '\u2019',
+ '\u201C',
+ '\u201D',
+ '\u2022',
+ '\u2013',
+ '\u2014',
+ '\u02DC',
+ '\u2122',
+ '\u0161',
+ '\u203A',
+ '\u0153',
+ '\u009D',
+ '\u017E',
+ '\u0178', // Last entry is 0x9F.
+ // 0x00->'\uFFFD' is handled programmatically.
+ // 0x0D->'\u000D' is a no-op.
+}
+
+// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
+// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
+// Precondition: b[src] == '&' && dst <= src.
+// attribute should be true if parsing an attribute value.
+func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+
+ // i starts at 1 because we already know that s[0] == '&'.
+ i, s := 1, b[src:]
+
+ if len(s) <= 1 {
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if s[i] == '#' {
+ if len(s) <= 3 { // We need to have at least "&#.".
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+ i++
+ c := s[i]
+ hex := false
+ if c == 'x' || c == 'X' {
+ hex = true
+ i++
+ }
+
+ x := '\x00'
+ for i < len(s) {
+ c = s[i]
+ i++
+ if hex {
+ if '0' <= c && c <= '9' {
+ x = 16*x + rune(c) - '0'
+ continue
+ } else if 'a' <= c && c <= 'f' {
+ x = 16*x + rune(c) - 'a' + 10
+ continue
+ } else if 'A' <= c && c <= 'F' {
+ x = 16*x + rune(c) - 'A' + 10
+ continue
+ }
+ } else if '0' <= c && c <= '9' {
+ x = 10*x + rune(c) - '0'
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ if i <= 3 { // No characters matched.
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if 0x80 <= x && x <= 0x9F {
+ // Replace characters from Windows-1252 with UTF-8 equivalents.
+ x = replacementTable[x-0x80]
+ } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
+ // Replace invalid characters with the replacement character.
+ x = '\uFFFD'
+ }
+
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ }
+
+ // Consume the maximum number of characters possible, with the
+ // consumed characters matching one of the named references.
+
+ for i < len(s) {
+ c := s[i]
+ i++
+ // Lower-cased characters are more common in entities, so we check for them first.
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ entityName := string(s[1:i])
+ if entityName == "" {
+ // No-op.
+ } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
+ // No-op.
+ } else if x := entity[entityName]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ } else if x := entity2[entityName]; x[0] != 0 {
+ dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
+ return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
+ } else if !attribute {
+ maxLen := len(entityName) - 1
+ if maxLen > longestEntityWithoutSemicolon {
+ maxLen = longestEntityWithoutSemicolon
+ }
+ for j := maxLen; j > 1; j-- {
+ if x := entity[entityName[:j]]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
+ }
+ }
+ }
+
+ dst1, src1 = dst+i, src+i
+ copy(b[dst:dst1], b[src:src1])
+ return dst1, src1
+}
+
+// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
+func unescape(b []byte) []byte {
+ for i, c := range b {
+ if c == '&' {
+ dst, src := unescapeEntity(b, i, i, false)
+ for src < len(b) {
+ c := b[src]
+ if c == '&' {
+ dst, src = unescapeEntity(b, dst, src, false)
+ } else {
+ b[dst] = c
+ dst, src = dst+1, src+1
+ }
+ }
+ return b[0:dst]
+ }
+ }
+ return b
+}
+
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+ for i, c := range b {
+ if 'A' <= c && c <= 'Z' {
+ b[i] = c + 'a' - 'A'
+ }
+ }
+ return b
+}
+
+const escapedChars = `&'<>"`
+
+func escape(w writer, s string) error {
+ i := strings.IndexAny(s, escapedChars)
+ for i != -1 {
+ if _, err := w.WriteString(s[:i]); err != nil {
+ return err
+ }
+ var esc string
+ switch s[i] {
+ case '&':
+ esc = "&amp;"
+ case '\'':
+ esc = "&apos;"
+ case '<':
+ esc = "&lt;"
+ case '>':
+ esc = "&gt;"
+ case '"':
+ esc = "&quot;"
+ default:
+ panic("unrecognized escape character")
+ }
+ s = s[i+1:]
+ if _, err := w.WriteString(esc); err != nil {
+ return err
+ }
+ i = strings.IndexAny(s, escapedChars)
+ }
+ _, err := w.WriteString(s)
+ return err
+}
+
+// EscapeString escapes special characters like "<" to become "&lt;". It
+// escapes only five such characters: amp, apos, lt, gt and quot.
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func EscapeString(s string) string {
+ if strings.IndexAny(s, escapedChars) == -1 {
+ return s
+ }
+ buf := bytes.NewBuffer(nil)
+ escape(buf, s)
+ return buf.String()
+}
+
+// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
+// larger range of entities than EscapeString escapes. For example, "&aacute;"
+// unescapes to "á", as does "&#225;" and "&xE1;".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func UnescapeString(s string) string {
+ for _, c := range s {
+ if c == '&' {
+ return string(unescape([]byte(s)))
+ }
+ }
+ return s
+}
diff --git a/libgo/go/html/foreign.go b/libgo/go/exp/html/foreign.go
index 3ba81ce4d6f..3ba81ce4d6f 100644
--- a/libgo/go/html/foreign.go
+++ b/libgo/go/exp/html/foreign.go
diff --git a/libgo/go/html/node.go b/libgo/go/exp/html/node.go
index 83f17308b18..83f17308b18 100644
--- a/libgo/go/html/node.go
+++ b/libgo/go/exp/html/node.go
diff --git a/libgo/go/html/parse.go b/libgo/go/exp/html/parse.go
index 04f4ae75334..04f4ae75334 100644
--- a/libgo/go/html/parse.go
+++ b/libgo/go/exp/html/parse.go
diff --git a/libgo/go/html/parse_test.go b/libgo/go/exp/html/parse_test.go
index 1528dffaafa..1528dffaafa 100644
--- a/libgo/go/html/parse_test.go
+++ b/libgo/go/exp/html/parse_test.go
diff --git a/libgo/go/html/render.go b/libgo/go/exp/html/render.go
index 07859faa7dd..07859faa7dd 100644
--- a/libgo/go/html/render.go
+++ b/libgo/go/exp/html/render.go
diff --git a/libgo/go/html/render_test.go b/libgo/go/exp/html/render_test.go
index 0584f35abdb..0584f35abdb 100644
--- a/libgo/go/html/render_test.go
+++ b/libgo/go/exp/html/render_test.go
diff --git a/libgo/go/html/testdata/webkit/README b/libgo/go/exp/html/testdata/webkit/README
index 9b4c2d8be0a..9b4c2d8be0a 100644
--- a/libgo/go/html/testdata/webkit/README
+++ b/libgo/go/exp/html/testdata/webkit/README
diff --git a/libgo/go/html/testdata/webkit/adoption01.dat b/libgo/go/exp/html/testdata/webkit/adoption01.dat
index 787e1b01e19..787e1b01e19 100644
--- a/libgo/go/html/testdata/webkit/adoption01.dat
+++ b/libgo/go/exp/html/testdata/webkit/adoption01.dat
diff --git a/libgo/go/html/testdata/webkit/adoption02.dat b/libgo/go/exp/html/testdata/webkit/adoption02.dat
index d18151b44f0..d18151b44f0 100644
--- a/libgo/go/html/testdata/webkit/adoption02.dat
+++ b/libgo/go/exp/html/testdata/webkit/adoption02.dat
diff --git a/libgo/go/html/testdata/webkit/comments01.dat b/libgo/go/exp/html/testdata/webkit/comments01.dat
index 44f18768300..44f18768300 100644
--- a/libgo/go/html/testdata/webkit/comments01.dat
+++ b/libgo/go/exp/html/testdata/webkit/comments01.dat
diff --git a/libgo/go/html/testdata/webkit/doctype01.dat b/libgo/go/exp/html/testdata/webkit/doctype01.dat
index ae457328a45..ae457328a45 100644
--- a/libgo/go/html/testdata/webkit/doctype01.dat
+++ b/libgo/go/exp/html/testdata/webkit/doctype01.dat
diff --git a/libgo/go/html/testdata/webkit/entities01.dat b/libgo/go/exp/html/testdata/webkit/entities01.dat
index c8073b7810b..c8073b7810b 100644
--- a/libgo/go/html/testdata/webkit/entities01.dat
+++ b/libgo/go/exp/html/testdata/webkit/entities01.dat
diff --git a/libgo/go/html/testdata/webkit/entities02.dat b/libgo/go/exp/html/testdata/webkit/entities02.dat
index e2fb42a078b..e2fb42a078b 100644
--- a/libgo/go/html/testdata/webkit/entities02.dat
+++ b/libgo/go/exp/html/testdata/webkit/entities02.dat
diff --git a/libgo/go/html/testdata/webkit/html5test-com.dat b/libgo/go/exp/html/testdata/webkit/html5test-com.dat
index d7cb71db054..d7cb71db054 100644
--- a/libgo/go/html/testdata/webkit/html5test-com.dat
+++ b/libgo/go/exp/html/testdata/webkit/html5test-com.dat
diff --git a/libgo/go/html/testdata/webkit/inbody01.dat b/libgo/go/exp/html/testdata/webkit/inbody01.dat
index 3f2bd374c03..3f2bd374c03 100644
--- a/libgo/go/html/testdata/webkit/inbody01.dat
+++ b/libgo/go/exp/html/testdata/webkit/inbody01.dat
diff --git a/libgo/go/html/testdata/webkit/isindex.dat b/libgo/go/exp/html/testdata/webkit/isindex.dat
index 88325ffe64c..88325ffe64c 100644
--- a/libgo/go/html/testdata/webkit/isindex.dat
+++ b/libgo/go/exp/html/testdata/webkit/isindex.dat
diff --git a/libgo/go/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat b/libgo/go/exp/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
index a5ebb1eb285..a5ebb1eb285 100644
--- a/libgo/go/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
+++ b/libgo/go/exp/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
Binary files differ
diff --git a/libgo/go/html/testdata/webkit/pending-spec-changes.dat b/libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat
index e00ee85d3bf..e00ee85d3bf 100644
--- a/libgo/go/html/testdata/webkit/pending-spec-changes.dat
+++ b/libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat
diff --git a/libgo/go/html/testdata/webkit/plain-text-unsafe.dat b/libgo/go/exp/html/testdata/webkit/plain-text-unsafe.dat
index 2f40e83babc..2f40e83babc 100644
--- a/libgo/go/html/testdata/webkit/plain-text-unsafe.dat
+++ b/libgo/go/exp/html/testdata/webkit/plain-text-unsafe.dat
diff --git a/libgo/go/html/testdata/webkit/scriptdata01.dat b/libgo/go/exp/html/testdata/webkit/scriptdata01.dat
index 76b67f4ba60..76b67f4ba60 100644
--- a/libgo/go/html/testdata/webkit/scriptdata01.dat
+++ b/libgo/go/exp/html/testdata/webkit/scriptdata01.dat
diff --git a/libgo/go/html/testdata/webkit/scripted/adoption01.dat b/libgo/go/exp/html/testdata/webkit/scripted/adoption01.dat
index 4e08d0e84a0..4e08d0e84a0 100644
--- a/libgo/go/html/testdata/webkit/scripted/adoption01.dat
+++ b/libgo/go/exp/html/testdata/webkit/scripted/adoption01.dat
diff --git a/libgo/go/html/testdata/webkit/scripted/webkit01.dat b/libgo/go/exp/html/testdata/webkit/scripted/webkit01.dat
index ef4a41ca00b..ef4a41ca00b 100644
--- a/libgo/go/html/testdata/webkit/scripted/webkit01.dat
+++ b/libgo/go/exp/html/testdata/webkit/scripted/webkit01.dat
diff --git a/libgo/go/html/testdata/webkit/tables01.dat b/libgo/go/exp/html/testdata/webkit/tables01.dat
index 88ef1fe2ee9..88ef1fe2ee9 100644
--- a/libgo/go/html/testdata/webkit/tables01.dat
+++ b/libgo/go/exp/html/testdata/webkit/tables01.dat
diff --git a/libgo/go/html/testdata/webkit/tests1.dat b/libgo/go/exp/html/testdata/webkit/tests1.dat
index cbf8bdda638..cbf8bdda638 100644
--- a/libgo/go/html/testdata/webkit/tests1.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests1.dat
diff --git a/libgo/go/html/testdata/webkit/tests10.dat b/libgo/go/exp/html/testdata/webkit/tests10.dat
index 4f8df86f208..4f8df86f208 100644
--- a/libgo/go/html/testdata/webkit/tests10.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests10.dat
diff --git a/libgo/go/html/testdata/webkit/tests11.dat b/libgo/go/exp/html/testdata/webkit/tests11.dat
index 638cde479f7..638cde479f7 100644
--- a/libgo/go/html/testdata/webkit/tests11.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests11.dat
diff --git a/libgo/go/html/testdata/webkit/tests12.dat b/libgo/go/exp/html/testdata/webkit/tests12.dat
index 63107d277b6..63107d277b6 100644
--- a/libgo/go/html/testdata/webkit/tests12.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests12.dat
diff --git a/libgo/go/html/testdata/webkit/tests14.dat b/libgo/go/exp/html/testdata/webkit/tests14.dat
index b8713f88582..b8713f88582 100644
--- a/libgo/go/html/testdata/webkit/tests14.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests14.dat
diff --git a/libgo/go/html/testdata/webkit/tests15.dat b/libgo/go/exp/html/testdata/webkit/tests15.dat
index 6ce1c0d1663..6ce1c0d1663 100644
--- a/libgo/go/html/testdata/webkit/tests15.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests15.dat
diff --git a/libgo/go/html/testdata/webkit/tests16.dat b/libgo/go/exp/html/testdata/webkit/tests16.dat
index 937dba9f42f..937dba9f42f 100644
--- a/libgo/go/html/testdata/webkit/tests16.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests16.dat
diff --git a/libgo/go/html/testdata/webkit/tests17.dat b/libgo/go/exp/html/testdata/webkit/tests17.dat
index 7b555f888de..7b555f888de 100644
--- a/libgo/go/html/testdata/webkit/tests17.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests17.dat
diff --git a/libgo/go/html/testdata/webkit/tests18.dat b/libgo/go/exp/html/testdata/webkit/tests18.dat
index 680e1f068a6..680e1f068a6 100644
--- a/libgo/go/html/testdata/webkit/tests18.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests18.dat
diff --git a/libgo/go/html/testdata/webkit/tests19.dat b/libgo/go/exp/html/testdata/webkit/tests19.dat
index 06222f5b9db..06222f5b9db 100644
--- a/libgo/go/html/testdata/webkit/tests19.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests19.dat
diff --git a/libgo/go/html/testdata/webkit/tests2.dat b/libgo/go/exp/html/testdata/webkit/tests2.dat
index 60d85922162..60d85922162 100644
--- a/libgo/go/html/testdata/webkit/tests2.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests2.dat
diff --git a/libgo/go/html/testdata/webkit/tests20.dat b/libgo/go/exp/html/testdata/webkit/tests20.dat
index 6bd825608f1..6bd825608f1 100644
--- a/libgo/go/html/testdata/webkit/tests20.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests20.dat
diff --git a/libgo/go/html/testdata/webkit/tests21.dat b/libgo/go/exp/html/testdata/webkit/tests21.dat
index 1260ec03e20..1260ec03e20 100644
--- a/libgo/go/html/testdata/webkit/tests21.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests21.dat
diff --git a/libgo/go/html/testdata/webkit/tests22.dat b/libgo/go/exp/html/testdata/webkit/tests22.dat
index aab27b2e904..aab27b2e904 100644
--- a/libgo/go/html/testdata/webkit/tests22.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests22.dat
diff --git a/libgo/go/html/testdata/webkit/tests23.dat b/libgo/go/exp/html/testdata/webkit/tests23.dat
index 34d2a73f1c7..34d2a73f1c7 100644
--- a/libgo/go/html/testdata/webkit/tests23.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests23.dat
diff --git a/libgo/go/html/testdata/webkit/tests24.dat b/libgo/go/exp/html/testdata/webkit/tests24.dat
index f6dc7eb48a5..f6dc7eb48a5 100644
--- a/libgo/go/html/testdata/webkit/tests24.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests24.dat
diff --git a/libgo/go/html/testdata/webkit/tests25.dat b/libgo/go/exp/html/testdata/webkit/tests25.dat
index 00de7295b71..00de7295b71 100644
--- a/libgo/go/html/testdata/webkit/tests25.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests25.dat
diff --git a/libgo/go/html/testdata/webkit/tests26.dat b/libgo/go/exp/html/testdata/webkit/tests26.dat
index da128e7794b..da128e7794b 100644
--- a/libgo/go/html/testdata/webkit/tests26.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests26.dat
diff --git a/libgo/go/html/testdata/webkit/tests3.dat b/libgo/go/exp/html/testdata/webkit/tests3.dat
index 38dc501be35..38dc501be35 100644
--- a/libgo/go/html/testdata/webkit/tests3.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests3.dat
diff --git a/libgo/go/html/testdata/webkit/tests4.dat b/libgo/go/exp/html/testdata/webkit/tests4.dat
index 3c506326d1f..3c506326d1f 100644
--- a/libgo/go/html/testdata/webkit/tests4.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests4.dat
diff --git a/libgo/go/html/testdata/webkit/tests5.dat b/libgo/go/exp/html/testdata/webkit/tests5.dat
index d7b5128a44d..d7b5128a44d 100644
--- a/libgo/go/html/testdata/webkit/tests5.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests5.dat
diff --git a/libgo/go/html/testdata/webkit/tests6.dat b/libgo/go/exp/html/testdata/webkit/tests6.dat
index f28ece4fb00..f28ece4fb00 100644
--- a/libgo/go/html/testdata/webkit/tests6.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests6.dat
diff --git a/libgo/go/html/testdata/webkit/tests7.dat b/libgo/go/exp/html/testdata/webkit/tests7.dat
index f5193c660bc..f5193c660bc 100644
--- a/libgo/go/html/testdata/webkit/tests7.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests7.dat
diff --git a/libgo/go/html/testdata/webkit/tests8.dat b/libgo/go/exp/html/testdata/webkit/tests8.dat
index 90e6c919e84..90e6c919e84 100644
--- a/libgo/go/html/testdata/webkit/tests8.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests8.dat
diff --git a/libgo/go/html/testdata/webkit/tests9.dat b/libgo/go/exp/html/testdata/webkit/tests9.dat
index 554e27aecf6..554e27aecf6 100644
--- a/libgo/go/html/testdata/webkit/tests9.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests9.dat
diff --git a/libgo/go/html/testdata/webkit/tests_innerHTML_1.dat b/libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat
index 052fac7d554..052fac7d554 100644
--- a/libgo/go/html/testdata/webkit/tests_innerHTML_1.dat
+++ b/libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat
diff --git a/libgo/go/html/testdata/webkit/tricky01.dat b/libgo/go/exp/html/testdata/webkit/tricky01.dat
index 08419924486..08419924486 100644
--- a/libgo/go/html/testdata/webkit/tricky01.dat
+++ b/libgo/go/exp/html/testdata/webkit/tricky01.dat
diff --git a/libgo/go/html/testdata/webkit/webkit01.dat b/libgo/go/exp/html/testdata/webkit/webkit01.dat
index 4101b216e18..4101b216e18 100644
--- a/libgo/go/html/testdata/webkit/webkit01.dat
+++ b/libgo/go/exp/html/testdata/webkit/webkit01.dat
diff --git a/libgo/go/html/testdata/webkit/webkit02.dat b/libgo/go/exp/html/testdata/webkit/webkit02.dat
index 2218f4298c5..2218f4298c5 100644
--- a/libgo/go/html/testdata/webkit/webkit02.dat
+++ b/libgo/go/exp/html/testdata/webkit/webkit02.dat
diff --git a/libgo/go/html/token.go b/libgo/go/exp/html/token.go
index 5a385a1b5c5..5a385a1b5c5 100644
--- a/libgo/go/html/token.go
+++ b/libgo/go/exp/html/token.go
diff --git a/libgo/go/html/token_test.go b/libgo/go/exp/html/token_test.go
index 672d60c4209..672d60c4209 100644
--- a/libgo/go/html/token_test.go
+++ b/libgo/go/exp/html/token_test.go
diff --git a/libgo/go/exp/norm/tables.go b/libgo/go/exp/norm/tables.go
index 55ff052dcbc..9044a72fd47 100644
--- a/libgo/go/exp/norm/tables.go
+++ b/libgo/go/exp/norm/tables.go
@@ -2804,12 +2804,12 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x0005, lo: 0x01},
{value: 0x068d, lo: 0xa2, hi: 0xa6},
// Block 0xc, offset 0xd
- {value: 0x0005, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x06ba, lo: 0x80, hi: 0x80},
{value: 0x06bf, lo: 0x82, hi: 0x82},
{value: 0x06c4, lo: 0x93, hi: 0x93},
// Block 0xd, offset 0xe
- {value: 0x0007, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x06c9, lo: 0xa9, hi: 0xa9},
{value: 0x06d0, lo: 0xb1, hi: 0xb1},
{value: 0x06d7, lo: 0xb4, hi: 0xb4},
@@ -2822,7 +2822,7 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x0724, lo: 0x9c, hi: 0x9d},
{value: 0x0732, lo: 0x9f, hi: 0x9f},
// Block 0x10, offset 0x11
- {value: 0x0007, lo: 0x02},
+ {value: 0x0000, lo: 0x02},
{value: 0x0739, lo: 0xb3, hi: 0xb3},
{value: 0x0740, lo: 0xb6, hi: 0xb6},
// Block 0x11, offset 0x12
@@ -2868,7 +2868,7 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x0854, lo: 0xb5, hi: 0xb6},
{value: 0x086c, lo: 0xb8, hi: 0xb8},
// Block 0x1a, offset 0x1b
- {value: 0x0007, lo: 0x07},
+ {value: 0x0000, lo: 0x07},
{value: 0x087d, lo: 0x81, hi: 0x81},
{value: 0x0884, lo: 0x93, hi: 0x93},
{value: 0x088b, lo: 0x9d, hi: 0x9d},
@@ -2880,7 +2880,7 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x0000, lo: 0x01},
{value: 0x08ae, lo: 0xa6, hi: 0xa6},
// Block 0x1c, offset 0x1d
- {value: 0x0007, lo: 0x08},
+ {value: 0x0000, lo: 0x08},
{value: 0x08b9, lo: 0x86, hi: 0x86},
{value: 0x08c0, lo: 0x88, hi: 0x88},
{value: 0x08c7, lo: 0x8a, hi: 0x8a},
@@ -2924,7 +2924,7 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x0006, lo: 0x01},
{value: 0x15b1, lo: 0x8d, hi: 0x8f},
// Block 0x23, offset 0x24
- {value: 0x0006, lo: 0x05},
+ {value: 0x0000, lo: 0x05},
{value: 0x15c3, lo: 0x84, hi: 0x84},
{value: 0x15c9, lo: 0x89, hi: 0x89},
{value: 0x15cf, lo: 0x8c, hi: 0x8c},
@@ -2960,7 +2960,7 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x0000, lo: 0x01},
{value: 0x1814, lo: 0x9c, hi: 0x9c},
// Block 0x29, offset 0x2a
- {value: 0x0007, lo: 0x0c},
+ {value: 0x0000, lo: 0x0c},
{value: 0x1c39, lo: 0x94, hi: 0x94},
{value: 0x1c4a, lo: 0x9e, hi: 0x9e},
{value: 0x1c58, lo: 0xac, hi: 0xac},
@@ -3084,7 +3084,7 @@ var nfcDecompSparseValues = [341]valueRange{
{value: 0x3191, lo: 0x83, hi: 0x84},
{value: 0x319b, lo: 0x86, hi: 0x8e},
// Block 0x33, offset 0x34
- {value: 0x0009, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x3a73, lo: 0x9a, hi: 0x9a},
{value: 0x3a7c, lo: 0x9c, hi: 0x9c},
{value: 0x3a85, lo: 0xab, hi: 0xab},
@@ -3897,10 +3897,10 @@ var nfkcDecompValues = [4224]uint16{
}
// nfkcDecompSparseOffset: 93 entries, 186 bytes
-var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10e, 0x11a, 0x11f, 0x122, 0x124, 0x126, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13b, 0x140, 0x14f, 0x15d, 0x15f, 0x161, 0x169, 0x179, 0x17b, 0x186, 0x18d, 0x198, 0x1a4, 0x1b5, 0x1c6, 0x1cd, 0x1de, 0x1ec, 0x1fa, 0x209, 0x21a, 0x21f, 0x22c, 0x230, 0x234, 0x238, 0x23a, 0x249, 0x24b, 0x24f}
+var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10c, 0x118, 0x11d, 0x120, 0x122, 0x124, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13e, 0x14d, 0x15b, 0x15d, 0x15f, 0x167, 0x177, 0x179, 0x184, 0x18b, 0x196, 0x1a2, 0x1b3, 0x1c4, 0x1cb, 0x1dc, 0x1ea, 0x1f8, 0x207, 0x218, 0x21d, 0x22a, 0x22e, 0x232, 0x236, 0x238, 0x247, 0x249, 0x24d}
-// nfkcDecompSparseValues: 605 entries, 2420 bytes
-var nfkcDecompSparseValues = [605]valueRange{
+// nfkcDecompSparseValues: 603 entries, 2412 bytes
+var nfkcDecompSparseValues = [603]valueRange{
// Block 0x0, offset 0x1
{value: 0x0002, lo: 0x0b},
{value: 0x0001, lo: 0xa0, hi: 0xa0},
@@ -4035,12 +4035,12 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0005, lo: 0x01},
{value: 0x06a6, lo: 0xb5, hi: 0xb8},
// Block 0x11, offset 0x12
- {value: 0x0005, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x06ba, lo: 0x80, hi: 0x80},
{value: 0x06bf, lo: 0x82, hi: 0x82},
{value: 0x06c4, lo: 0x93, hi: 0x93},
// Block 0x12, offset 0x13
- {value: 0x0007, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x06c9, lo: 0xa9, hi: 0xa9},
{value: 0x06d0, lo: 0xb1, hi: 0xb1},
{value: 0x06d7, lo: 0xb4, hi: 0xb4},
@@ -4053,7 +4053,7 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0724, lo: 0x9c, hi: 0x9d},
{value: 0x0732, lo: 0x9f, hi: 0x9f},
// Block 0x15, offset 0x16
- {value: 0x0007, lo: 0x02},
+ {value: 0x0000, lo: 0x02},
{value: 0x0739, lo: 0xb3, hi: 0xb3},
{value: 0x0740, lo: 0xb6, hi: 0xb6},
// Block 0x16, offset 0x17
@@ -4111,7 +4111,7 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0854, lo: 0xb5, hi: 0xb7},
{value: 0x086c, lo: 0xb8, hi: 0xb9},
// Block 0x23, offset 0x24
- {value: 0x0007, lo: 0x07},
+ {value: 0x0000, lo: 0x07},
{value: 0x087d, lo: 0x81, hi: 0x81},
{value: 0x0884, lo: 0x93, hi: 0x93},
{value: 0x088b, lo: 0x9d, hi: 0x9d},
@@ -4126,7 +4126,7 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0000, lo: 0x01},
{value: 0x08b5, lo: 0xbc, hi: 0xbc},
// Block 0x26, offset 0x27
- {value: 0x0007, lo: 0x08},
+ {value: 0x0000, lo: 0x08},
{value: 0x08b9, lo: 0x86, hi: 0x86},
{value: 0x08c0, lo: 0x88, hi: 0x88},
{value: 0x08c7, lo: 0x8a, hi: 0x8a},
@@ -4209,16 +4209,14 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0006, lo: 0x01},
{value: 0x15b1, lo: 0x8d, hi: 0x8f},
// Block 0x2f, offset 0x30
- {value: 0x0006, lo: 0x09},
+ {value: 0x0007, lo: 0x07},
{value: 0x15c3, lo: 0x84, hi: 0x84},
{value: 0x15c9, lo: 0x89, hi: 0x89},
{value: 0x15cf, lo: 0x8c, hi: 0x8c},
{value: 0x15d5, lo: 0xa4, hi: 0xa4},
{value: 0x15db, lo: 0xa6, hi: 0xa6},
- {value: 0x15e1, lo: 0xac, hi: 0xac},
- {value: 0x15e8, lo: 0xad, hi: 0xad},
- {value: 0x15f2, lo: 0xaf, hi: 0xaf},
- {value: 0x15f9, lo: 0xb0, hi: 0xb0},
+ {value: 0x15e1, lo: 0xac, hi: 0xad},
+ {value: 0x15f2, lo: 0xaf, hi: 0xb0},
// Block 0x30, offset 0x31
{value: 0x0006, lo: 0x0b},
{value: 0x1603, lo: 0x81, hi: 0x81},
@@ -4249,9 +4247,9 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0000, lo: 0x01},
{value: 0x17fc, lo: 0x8c, hi: 0x8c},
// Block 0x35, offset 0x36
- {value: 0x0004, lo: 0x02},
- {value: 0x1809, lo: 0xb4, hi: 0xb5},
- {value: 0x1810, lo: 0xb6, hi: 0xb6},
+ {value: 0x0003, lo: 0x02},
+ {value: 0x1809, lo: 0xb4, hi: 0xb4},
+ {value: 0x180d, lo: 0xb5, hi: 0xb6},
// Block 0x36, offset 0x37
{value: 0x0000, lo: 0x01},
{value: 0x1814, lo: 0x9c, hi: 0x9c},
@@ -4280,17 +4278,17 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x0004, lo: 0x01},
{value: 0x1b26, lo: 0x80, hi: 0x95},
// Block 0x3f, offset 0x40
- {value: 0x0300, lo: 0x04},
+ {value: 0x0004, lo: 0x04},
{value: 0x0001, lo: 0x80, hi: 0x80},
{value: 0x1b7e, lo: 0xb6, hi: 0xb6},
- {value: 0x1882, lo: 0xb8, hi: 0xb9},
- {value: 0x1b86, lo: 0xba, hi: 0xba},
+ {value: 0x1882, lo: 0xb8, hi: 0xb8},
+ {value: 0x1b82, lo: 0xb9, hi: 0xba},
// Block 0x40, offset 0x41
- {value: 0x0007, lo: 0x0e},
+ {value: 0x0005, lo: 0x0e},
{value: 0x1c39, lo: 0x94, hi: 0x94},
- {value: 0x1c40, lo: 0x9b, hi: 0x9b},
- {value: 0x1c45, lo: 0x9c, hi: 0x9c},
- {value: 0x1c4a, lo: 0x9e, hi: 0x9f},
+ {value: 0x1c40, lo: 0x9b, hi: 0x9c},
+ {value: 0x1c4a, lo: 0x9e, hi: 0x9e},
+ {value: 0x1c51, lo: 0x9f, hi: 0x9f},
{value: 0x1c58, lo: 0xac, hi: 0xac},
{value: 0x1c5f, lo: 0xae, hi: 0xae},
{value: 0x1c66, lo: 0xb0, hi: 0xb0},
@@ -4543,7 +4541,7 @@ var nfkcDecompSparseValues = [605]valueRange{
{value: 0x3a53, lo: 0xa6, hi: 0xa6},
{value: 0x3a57, lo: 0xa8, hi: 0xae},
// Block 0x55, offset 0x56
- {value: 0x0009, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x3a73, lo: 0x9a, hi: 0x9a},
{value: 0x3a7c, lo: 0x9c, hi: 0x9c},
{value: 0x3a85, lo: 0xab, hi: 0xab},
@@ -5760,10 +5758,10 @@ var charInfoValues = [1024]uint16{
}
// charInfoSparseOffset: 156 entries, 312 bytes
-var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd7, 0xda, 0xe3, 0xe5, 0xed, 0xf1, 0xf3, 0xf6, 0xf9, 0xff, 0x10f, 0x11b, 0x11d, 0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x134, 0x137, 0x139, 0x13c, 0x13f, 0x143, 0x152, 0x15a, 0x15c, 0x15f, 0x161, 0x16a, 0x16e, 0x172, 0x174, 0x183, 0x187, 0x18d, 0x195, 0x199, 0x1a2, 0x1ab, 0x1b6, 0x1bc, 0x1c0, 0x1ce, 0x1dd, 0x1e1, 0x1e8, 0x1ed, 0x1fc, 0x208, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21d, 0x220, 0x222, 0x224, 0x226, 0x228, 0x231, 0x233, 0x236, 0x239, 0x23c, 0x23e, 0x241, 0x243, 0x245, 0x247, 0x24a, 0x24c, 0x24e, 0x250, 0x252, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x262, 0x26c, 0x26f, 0x271, 0x27b, 0x280, 0x282, 0x284, 0x286, 0x288, 0x28b, 0x28e, 0x292, 0x29a, 0x29c, 0x29e, 0x2a5, 0x2a7, 0x2ae, 0x2b6, 0x2bd, 0x2c3, 0x2c5, 0x2c7, 0x2ca, 0x2d3, 0x2d6, 0x2dd, 0x2e2, 0x2e5, 0x2e8, 0x2ec, 0x2ee, 0x2f0, 0x2f3, 0x2f6}
+var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd6, 0xd9, 0xe2, 0xe4, 0xec, 0xf0, 0xf2, 0xf5, 0xf8, 0xfe, 0x10e, 0x11a, 0x11c, 0x122, 0x124, 0x126, 0x128, 0x12a, 0x12c, 0x12e, 0x130, 0x133, 0x136, 0x138, 0x13b, 0x13e, 0x142, 0x151, 0x159, 0x15b, 0x15e, 0x160, 0x169, 0x16d, 0x171, 0x173, 0x182, 0x186, 0x18c, 0x194, 0x198, 0x1a1, 0x1aa, 0x1b5, 0x1bb, 0x1bf, 0x1cd, 0x1dc, 0x1e0, 0x1e7, 0x1ec, 0x1fa, 0x206, 0x209, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21e, 0x220, 0x222, 0x224, 0x226, 0x22f, 0x231, 0x234, 0x237, 0x23a, 0x23c, 0x23f, 0x241, 0x243, 0x245, 0x248, 0x24a, 0x24c, 0x24e, 0x250, 0x256, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x26a, 0x26d, 0x26f, 0x279, 0x27e, 0x280, 0x282, 0x284, 0x286, 0x289, 0x28c, 0x290, 0x298, 0x29a, 0x29c, 0x2a3, 0x2a5, 0x2ab, 0x2b3, 0x2ba, 0x2c0, 0x2c2, 0x2c4, 0x2c7, 0x2d0, 0x2d3, 0x2da, 0x2df, 0x2e2, 0x2e5, 0x2e9, 0x2eb, 0x2ed, 0x2f0, 0x2f3}
-// charInfoSparseValues: 760 entries, 3040 bytes
-var charInfoSparseValues = [760]valueRange{
+// charInfoSparseValues: 757 entries, 3028 bytes
+var charInfoSparseValues = [757]valueRange{
// Block 0x0, offset 0x1
{value: 0x0000, lo: 0x07},
{value: 0x3000, lo: 0xa0, hi: 0xa0},
@@ -5942,7 +5940,7 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x0000, lo: 0x01},
{value: 0x00dc, lo: 0x99, hi: 0x9b},
// Block 0x14, offset 0x15
- {value: 0x7700, lo: 0x07},
+ {value: 0x0000, lo: 0x07},
{value: 0x8800, lo: 0xa8, hi: 0xa8},
{value: 0x1100, lo: 0xa9, hi: 0xa9},
{value: 0x8800, lo: 0xb0, hi: 0xb0},
@@ -5958,7 +5956,7 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x00e6, lo: 0x93, hi: 0x94},
{value: 0x3300, lo: 0x98, hi: 0x9f},
// Block 0x16, offset 0x17
- {value: 0x65f9, lo: 0x02},
+ {value: 0x0000, lo: 0x02},
{value: 0x0007, lo: 0xbc, hi: 0xbc},
{value: 0x6600, lo: 0xbe, hi: 0xbe},
// Block 0x17, offset 0x18
@@ -5994,7 +5992,7 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x6600, lo: 0x96, hi: 0x97},
{value: 0x3300, lo: 0x9c, hi: 0x9d},
// Block 0x1d, offset 0x1e
- {value: 0x5500, lo: 0x03},
+ {value: 0x0000, lo: 0x03},
{value: 0x8800, lo: 0x92, hi: 0x92},
{value: 0x1100, lo: 0x94, hi: 0x94},
{value: 0x6600, lo: 0xbe, hi: 0xbe},
@@ -6005,14 +6003,13 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x0009, lo: 0x8d, hi: 0x8d},
{value: 0x6600, lo: 0x97, hi: 0x97},
// Block 0x1f, offset 0x20
- {value: 0x004b, lo: 0x05},
+ {value: 0x6607, lo: 0x04},
{value: 0x8800, lo: 0x86, hi: 0x86},
{value: 0x1100, lo: 0x88, hi: 0x88},
{value: 0x0009, lo: 0x8d, hi: 0x8d},
- {value: 0x0054, lo: 0x95, hi: 0x95},
- {value: 0x665b, lo: 0x96, hi: 0x96},
+ {value: 0x0054, lo: 0x95, hi: 0x96},
// Block 0x20, offset 0x21
- {value: 0x87f9, lo: 0x02},
+ {value: 0x0000, lo: 0x02},
{value: 0x0007, lo: 0xbc, hi: 0xbc},
{value: 0x8800, lo: 0xbf, hi: 0xbf},
// Block 0x21, offset 0x22
@@ -6126,7 +6123,7 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x0009, lo: 0x94, hi: 0x94},
{value: 0x0009, lo: 0xb4, hi: 0xb4},
// Block 0x35, offset 0x36
- {value: 0x00dd, lo: 0x02},
+ {value: 0x0000, lo: 0x02},
{value: 0x0009, lo: 0x92, hi: 0x92},
{value: 0x00e6, lo: 0x9d, hi: 0x9d},
// Block 0x36, offset 0x37
@@ -6340,7 +6337,7 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x8800, lo: 0x92, hi: 0x92},
{value: 0x8800, lo: 0x94, hi: 0x94},
// Block 0x52, offset 0x53
- {value: 0x7700, lo: 0x0e},
+ {value: 0x0000, lo: 0x0d},
{value: 0x8800, lo: 0x83, hi: 0x83},
{value: 0x1100, lo: 0x84, hi: 0x84},
{value: 0x8800, lo: 0x88, hi: 0x88},
@@ -6348,12 +6345,11 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x8800, lo: 0x8b, hi: 0x8b},
{value: 0x1100, lo: 0x8c, hi: 0x8c},
{value: 0x8800, lo: 0xa3, hi: 0xa3},
- {value: 0x1100, lo: 0xa4, hi: 0xa5},
+ {value: 0x1100, lo: 0xa4, hi: 0xa4},
+ {value: 0x8800, lo: 0xa5, hi: 0xa5},
{value: 0x1100, lo: 0xa6, hi: 0xa6},
- {value: 0x3000, lo: 0xac, hi: 0xac},
- {value: 0x3000, lo: 0xad, hi: 0xad},
- {value: 0x3000, lo: 0xaf, hi: 0xaf},
- {value: 0x3000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3000, lo: 0xac, hi: 0xad},
+ {value: 0x3000, lo: 0xaf, hi: 0xb0},
{value: 0x8800, lo: 0xbc, hi: 0xbc},
// Block 0x53, offset 0x54
{value: 0x0000, lo: 0x0b},
@@ -6581,22 +6577,21 @@ var charInfoSparseValues = [760]valueRange{
{value: 0x0000, lo: 0x01},
{value: 0x00dc, lo: 0xbd, hi: 0xbd},
// Block 0x89, offset 0x8a
- {value: 0x0000, lo: 0x06},
+ {value: 0x00db, lo: 0x05},
{value: 0x00dc, lo: 0x8d, hi: 0x8d},
{value: 0x00e6, lo: 0x8f, hi: 0x8f},
{value: 0x00e6, lo: 0xb8, hi: 0xb8},
- {value: 0x0001, lo: 0xb9, hi: 0xb9},
- {value: 0x00dc, lo: 0xba, hi: 0xba},
+ {value: 0x0001, lo: 0xb9, hi: 0xba},
{value: 0x0009, lo: 0xbf, hi: 0xbf},
// Block 0x8a, offset 0x8b
- {value: 0x7700, lo: 0x07},
+ {value: 0x65fe, lo: 0x07},
{value: 0x8800, lo: 0x99, hi: 0x99},
- {value: 0x1100, lo: 0x9a, hi: 0x9b},
+ {value: 0x1100, lo: 0x9a, hi: 0x9a},
+ {value: 0x8800, lo: 0x9b, hi: 0x9b},
{value: 0x1100, lo: 0x9c, hi: 0x9c},
{value: 0x8800, lo: 0xa5, hi: 0xa5},
{value: 0x1100, lo: 0xab, hi: 0xab},
- {value: 0x0009, lo: 0xb9, hi: 0xb9},
- {value: 0x6607, lo: 0xba, hi: 0xba},
+ {value: 0x0009, lo: 0xb9, hi: 0xba},
// Block 0x8b, offset 0x8c
{value: 0x0000, lo: 0x06},
{value: 0x3300, lo: 0x9e, hi: 0xa4},
@@ -6768,4 +6763,4 @@ var charInfoLookup = [1152]uint8{
var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:], charInfoSparseValues[:], charInfoSparseOffset[:], 16}
-// Total size of tables: 48KB (48756 bytes)
+// Total size of tables: 48KB (48736 bytes)
diff --git a/libgo/go/exp/norm/triegen.go b/libgo/go/exp/norm/triegen.go
index 5edadac0a41..4ad9e0e057c 100644
--- a/libgo/go/exp/norm/triegen.go
+++ b/libgo/go/exp/norm/triegen.go
@@ -65,11 +65,13 @@ func (n trieNode) mostFrequentStride() int {
counts[stride]++
}
v = t.value
+ } else {
+ v = 0
}
}
var maxs, maxc int
for stride, cnt := range counts {
- if cnt > maxc {
+ if cnt > maxc || (cnt == maxc && stride < maxs) {
maxs, maxc = stride, cnt
}
}
diff --git a/libgo/go/exp/spdy/read.go b/libgo/go/exp/spdy/read.go
deleted file mode 100644
index 4830a1d6bfd..00000000000
--- a/libgo/go/exp/spdy/read.go
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spdy
-
-import (
- "compress/zlib"
- "encoding/binary"
- "io"
- "net/http"
- "strings"
-)
-
-func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
- return f.readSynStreamFrame(h, frame)
-}
-
-func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
- return f.readSynReplyFrame(h, frame)
-}
-
-func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
- return err
- }
- return nil
-}
-
-func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- var numSettings uint32
- if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
- return err
- }
- frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
- for i := uint32(0); i < numSettings; i++ {
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
- return err
- }
- frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
- frame.FlagIdValues[i].Id &= 0xffffff
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (frame *NoopFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- return nil
-}
-
-func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
- return err
- }
- return nil
-}
-
-func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
- return err
- }
- return nil
-}
-
-func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
- return f.readHeadersFrame(h, frame)
-}
-
-func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
- ctor, ok := cframeCtor[frameType]
- if !ok {
- return nil, &Error{Err: InvalidControlFrame}
- }
- return ctor(), nil
-}
-
-var cframeCtor = map[ControlFrameType]func() controlFrame{
- TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
- TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
- TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
- TypeSettings: func() controlFrame { return new(SettingsFrame) },
- TypeNoop: func() controlFrame { return new(NoopFrame) },
- TypePing: func() controlFrame { return new(PingFrame) },
- TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
- TypeHeaders: func() controlFrame { return new(HeadersFrame) },
- // TODO(willchan): Add TypeWindowUpdate
-}
-
-func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
- if f.headerDecompressor != nil {
- f.headerReader.N = payloadSize
- return nil
- }
- f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
- decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(HeaderDictionary))
- if err != nil {
- return err
- }
- f.headerDecompressor = decompressor
- return nil
-}
-
-// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
-func (f *Framer) ReadFrame() (Frame, error) {
- var firstWord uint32
- if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
- return nil, err
- }
- if (firstWord & 0x80000000) != 0 {
- frameType := ControlFrameType(firstWord & 0xffff)
- version := uint16(0x7fff & (firstWord >> 16))
- return f.parseControlFrame(version, frameType)
- }
- return f.parseDataFrame(firstWord & 0x7fffffff)
-}
-
-func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
- var length uint32
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- flags := ControlFlags((length & 0xff000000) >> 24)
- length &= 0xffffff
- header := ControlFrameHeader{version, frameType, flags, length}
- cframe, err := newControlFrame(frameType)
- if err != nil {
- return nil, err
- }
- if err = cframe.read(header, f); err != nil {
- return nil, err
- }
- return cframe, nil
-}
-
-func parseHeaderValueBlock(r io.Reader, streamId uint32) (http.Header, error) {
- var numHeaders uint16
- if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
- return nil, err
- }
- var e error
- h := make(http.Header, int(numHeaders))
- for i := 0; i < int(numHeaders); i++ {
- var length uint16
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- nameBytes := make([]byte, length)
- if _, err := io.ReadFull(r, nameBytes); err != nil {
- return nil, err
- }
- name := string(nameBytes)
- if name != strings.ToLower(name) {
- e = &Error{UnlowercasedHeaderName, streamId}
- name = strings.ToLower(name)
- }
- if h[name] != nil {
- e = &Error{DuplicateHeaders, streamId}
- }
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- value := make([]byte, length)
- if _, err := io.ReadFull(r, value); err != nil {
- return nil, err
- }
- valueList := strings.Split(string(value), "\x00")
- for _, v := range valueList {
- h.Add(name, v)
- }
- }
- if e != nil {
- return h, e
- }
- return h, nil
-}
-
-func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
- frame.CFHeader = h
- var err error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
- return err
- }
- if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
- return err
- }
- frame.Priority >>= 14
-
- reader := f.r
- if !f.headerCompressionDisabled {
- f.uncorkHeaderDecompressor(int64(h.length - 10))
- reader = f.headerDecompressor
- }
-
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && ((err == io.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- // Remove this condition when we bump Version to 3.
- if Version >= 3 {
- for h := range frame.Headers {
- if invalidReqHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- }
- return nil
-}
-
-func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
- frame.CFHeader = h
- var err error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- var unused uint16
- if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- f.uncorkHeaderDecompressor(int64(h.length - 6))
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && ((err == io.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- // Remove this condition when we bump Version to 3.
- if Version >= 3 {
- for h := range frame.Headers {
- if invalidRespHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- }
- return nil
-}
-
-func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
- frame.CFHeader = h
- var err error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- var unused uint16
- if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- f.uncorkHeaderDecompressor(int64(h.length - 6))
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && ((err == io.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
-
- // Remove this condition when we bump Version to 3.
- if Version >= 3 {
- var invalidHeaders map[string]bool
- if frame.StreamId%2 == 0 {
- invalidHeaders = invalidReqHeaders
- } else {
- invalidHeaders = invalidRespHeaders
- }
- for h := range frame.Headers {
- if invalidHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- }
- return nil
-}
-
-func (f *Framer) parseDataFrame(streamId uint32) (*DataFrame, error) {
- var length uint32
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- var frame DataFrame
- frame.StreamId = streamId
- frame.Flags = DataFlags(length >> 24)
- length &= 0xffffff
- frame.Data = make([]byte, length)
- if _, err := io.ReadFull(f.r, frame.Data); err != nil {
- return nil, err
- }
- return &frame, nil
-}
diff --git a/libgo/go/exp/spdy/spdy_test.go b/libgo/go/exp/spdy/spdy_test.go
deleted file mode 100644
index c1cad4b37c6..00000000000
--- a/libgo/go/exp/spdy/spdy_test.go
+++ /dev/null
@@ -1,497 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spdy
-
-import (
- "bytes"
- "io"
- "net/http"
- "reflect"
- "testing"
-)
-
-func TestHeaderParsing(t *testing.T) {
- headers := http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- }
- var headerValueBlockBuf bytes.Buffer
- writeHeaderValueBlock(&headerValueBlockBuf, headers)
-
- const bogusStreamId = 1
- newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
- if err != nil {
- t.Fatal("parseHeaderValueBlock:", err)
- }
-
- if !reflect.DeepEqual(headers, newHeaders) {
- t.Fatal("got: ", newHeaders, "\nwant: ", headers)
- }
-}
-
-func TestCreateParseSynStreamFrame(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer := &Framer{
- headerCompressionDisabled: true,
- w: buffer,
- headerBuf: new(bytes.Buffer),
- r: buffer,
- }
- synStreamFrame := SynStreamFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeSynStream,
- },
- Headers: http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- },
- }
- if err := framer.WriteFrame(&synStreamFrame); err != nil {
- t.Fatal("WriteFrame without compression:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame without compression:", err)
- }
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
- }
-
- // Test again with compression
- buffer.Reset()
- framer, err = NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- if err := framer.WriteFrame(&synStreamFrame); err != nil {
- t.Fatal("WriteFrame with compression:", err)
- }
- frame, err = framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame with compression:", err)
- }
- parsedSynStreamFrame, ok = frame.(*SynStreamFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
- }
-}
-
-func TestCreateParseSynReplyFrame(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer := &Framer{
- headerCompressionDisabled: true,
- w: buffer,
- headerBuf: new(bytes.Buffer),
- r: buffer,
- }
- synReplyFrame := SynReplyFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeSynReply,
- },
- Headers: http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- },
- }
- if err := framer.WriteFrame(&synReplyFrame); err != nil {
- t.Fatal("WriteFrame without compression:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame without compression:", err)
- }
- parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
- t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
- }
-
- // Test again with compression
- buffer.Reset()
- framer, err = NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- if err := framer.WriteFrame(&synReplyFrame); err != nil {
- t.Fatal("WriteFrame with compression:", err)
- }
- frame, err = framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame with compression:", err)
- }
- parsedSynReplyFrame, ok = frame.(*SynReplyFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
- t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
- }
-}
-
-func TestCreateParseRstStream(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- rstStreamFrame := RstStreamFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeRstStream,
- },
- StreamId: 1,
- Status: InvalidStream,
- }
- if err := framer.WriteFrame(&rstStreamFrame); err != nil {
- t.Fatal("WriteFrame:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame:", err)
- }
- parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
- t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
- }
-}
-
-func TestCreateParseSettings(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- settingsFrame := SettingsFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeSettings,
- },
- FlagIdValues: []SettingsFlagIdValue{
- {FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
- {FlagSettingsPersisted, SettingsUploadBandwidth, 1},
- },
- }
- if err := framer.WriteFrame(&settingsFrame); err != nil {
- t.Fatal("WriteFrame:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame:", err)
- }
- parsedSettingsFrame, ok := frame.(*SettingsFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
- t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
- }
-}
-
-func TestCreateParseNoop(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- noopFrame := NoopFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeNoop,
- },
- }
- if err := framer.WriteFrame(&noopFrame); err != nil {
- t.Fatal("WriteFrame:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame:", err)
- }
- parsedNoopFrame, ok := frame.(*NoopFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(noopFrame, *parsedNoopFrame) {
- t.Fatal("got: ", *parsedNoopFrame, "\nwant: ", noopFrame)
- }
-}
-
-func TestCreateParsePing(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- pingFrame := PingFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypePing,
- },
- Id: 31337,
- }
- if err := framer.WriteFrame(&pingFrame); err != nil {
- t.Fatal("WriteFrame:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame:", err)
- }
- parsedPingFrame, ok := frame.(*PingFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
- t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
- }
-}
-
-func TestCreateParseGoAway(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- goAwayFrame := GoAwayFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeGoAway,
- },
- LastGoodStreamId: 31337,
- }
- if err := framer.WriteFrame(&goAwayFrame); err != nil {
- t.Fatal("WriteFrame:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame:", err)
- }
- parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
- t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
- }
-}
-
-func TestCreateParseHeadersFrame(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer := &Framer{
- headerCompressionDisabled: true,
- w: buffer,
- headerBuf: new(bytes.Buffer),
- r: buffer,
- }
- headersFrame := HeadersFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeHeaders,
- },
- }
- headersFrame.Headers = http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- }
- if err := framer.WriteFrame(&headersFrame); err != nil {
- t.Fatal("WriteFrame without compression:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame without compression:", err)
- }
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
- }
-
- // Test again with compression
- buffer.Reset()
- framer, err = NewFramer(buffer, buffer)
- if err := framer.WriteFrame(&headersFrame); err != nil {
- t.Fatal("WriteFrame with compression:", err)
- }
- frame, err = framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame with compression:", err)
- }
- parsedHeadersFrame, ok = frame.(*HeadersFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
- }
-}
-
-func TestCreateParseDataFrame(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- dataFrame := DataFrame{
- StreamId: 1,
- Data: []byte{'h', 'e', 'l', 'l', 'o'},
- }
- if err := framer.WriteFrame(&dataFrame); err != nil {
- t.Fatal("WriteFrame:", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame:", err)
- }
- parsedDataFrame, ok := frame.(*DataFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
- t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
- }
-}
-
-func TestCompressionContextAcrossFrames(t *testing.T) {
- buffer := new(bytes.Buffer)
- framer, err := NewFramer(buffer, buffer)
- if err != nil {
- t.Fatal("Failed to create new framer:", err)
- }
- headersFrame := HeadersFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeHeaders,
- },
- Headers: http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- },
- }
- if err := framer.WriteFrame(&headersFrame); err != nil {
- t.Fatal("WriteFrame (HEADERS):", err)
- }
- synStreamFrame := SynStreamFrame{ControlFrameHeader{Version, TypeSynStream, 0, 0}, 0, 0, 0, nil}
- synStreamFrame.Headers = http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- }
- if err := framer.WriteFrame(&synStreamFrame); err != nil {
- t.Fatal("WriteFrame (SYN_STREAM):", err)
- }
- frame, err := framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
- }
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
- if !ok {
- t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
- }
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
- }
- frame, err = framer.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
- }
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
- if !ok {
- t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
- }
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
- }
-}
-
-func TestMultipleSPDYFrames(t *testing.T) {
- // Initialize the framers.
- pr1, pw1 := io.Pipe()
- pr2, pw2 := io.Pipe()
- writer, err := NewFramer(pw1, pr2)
- if err != nil {
- t.Fatal("Failed to create writer:", err)
- }
- reader, err := NewFramer(pw2, pr1)
- if err != nil {
- t.Fatal("Failed to create reader:", err)
- }
-
- // Set up the frames we're actually transferring.
- headersFrame := HeadersFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeHeaders,
- },
- Headers: http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- },
- }
- synStreamFrame := SynStreamFrame{
- CFHeader: ControlFrameHeader{
- version: Version,
- frameType: TypeSynStream,
- },
- Headers: http.Header{
- "Url": []string{"http://www.google.com/"},
- "Method": []string{"get"},
- "Version": []string{"http/1.1"},
- },
- }
-
- // Start the goroutines to write the frames.
- go func() {
- if err := writer.WriteFrame(&headersFrame); err != nil {
- t.Fatal("WriteFrame (HEADERS): ", err)
- }
- if err := writer.WriteFrame(&synStreamFrame); err != nil {
- t.Fatal("WriteFrame (SYN_STREAM): ", err)
- }
- }()
-
- // Read the frames and verify they look as expected.
- frame, err := reader.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame (HEADERS): ", err)
- }
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type:", frame)
- }
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
- }
- frame, err = reader.ReadFrame()
- if err != nil {
- t.Fatal("ReadFrame (SYN_STREAM):", err)
- }
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
- if !ok {
- t.Fatal("Parsed incorrect frame type.")
- }
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
- }
-}
diff --git a/libgo/go/exp/spdy/types.go b/libgo/go/exp/spdy/types.go
deleted file mode 100644
index 2648c4f75f9..00000000000
--- a/libgo/go/exp/spdy/types.go
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spdy
-
-import (
- "bytes"
- "compress/zlib"
- "io"
- "net/http"
-)
-
-// Data Frame Format
-// +----------------------------------+
-// |0| Stream-ID (31bits) |
-// +----------------------------------+
-// | flags (8) | Length (24 bits) |
-// +----------------------------------+
-// | Data |
-// +----------------------------------+
-//
-// Control Frame Format
-// +----------------------------------+
-// |1| Version(15bits) | Type(16bits) |
-// +----------------------------------+
-// | flags (8) | Length (24 bits) |
-// +----------------------------------+
-// | Data |
-// +----------------------------------+
-//
-// Control Frame: SYN_STREAM
-// +----------------------------------+
-// |1|000000000000001|0000000000000001|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | >= 12
-// +----------------------------------+
-// |X| Stream-ID(31bits) |
-// +----------------------------------+
-// |X|Associated-To-Stream-ID (31bits)|
-// +----------------------------------+
-// |Pri| unused | Length (16bits)|
-// +----------------------------------+
-//
-// Control Frame: SYN_REPLY
-// +----------------------------------+
-// |1|000000000000001|0000000000000010|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | >= 8
-// +----------------------------------+
-// |X| Stream-ID(31bits) |
-// +----------------------------------+
-// | unused (16 bits)| Length (16bits)|
-// +----------------------------------+
-//
-// Control Frame: RST_STREAM
-// +----------------------------------+
-// |1|000000000000001|0000000000000011|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | >= 4
-// +----------------------------------+
-// |X| Stream-ID(31bits) |
-// +----------------------------------+
-// | Status code (32 bits) |
-// +----------------------------------+
-//
-// Control Frame: SETTINGS
-// +----------------------------------+
-// |1|000000000000001|0000000000000100|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) |
-// +----------------------------------+
-// | # of entries (32) |
-// +----------------------------------+
-//
-// Control Frame: NOOP
-// +----------------------------------+
-// |1|000000000000001|0000000000000101|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | = 0
-// +----------------------------------+
-//
-// Control Frame: PING
-// +----------------------------------+
-// |1|000000000000001|0000000000000110|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | = 4
-// +----------------------------------+
-// | Unique id (32 bits) |
-// +----------------------------------+
-//
-// Control Frame: GOAWAY
-// +----------------------------------+
-// |1|000000000000001|0000000000000111|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | = 4
-// +----------------------------------+
-// |X| Last-accepted-stream-id |
-// +----------------------------------+
-//
-// Control Frame: HEADERS
-// +----------------------------------+
-// |1|000000000000001|0000000000001000|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | >= 8
-// +----------------------------------+
-// |X| Stream-ID (31 bits) |
-// +----------------------------------+
-// | unused (16 bits)| Length (16bits)|
-// +----------------------------------+
-//
-// Control Frame: WINDOW_UPDATE
-// +----------------------------------+
-// |1|000000000000001|0000000000001001|
-// +----------------------------------+
-// | flags (8) | Length (24 bits) | = 8
-// +----------------------------------+
-// |X| Stream-ID (31 bits) |
-// +----------------------------------+
-// | Delta-Window-Size (32 bits) |
-// +----------------------------------+
-
-// Version is the protocol version number that this package implements.
-const Version = 2
-
-// ControlFrameType stores the type field in a control frame header.
-type ControlFrameType uint16
-
-// Control frame type constants
-const (
- TypeSynStream ControlFrameType = 0x0001
- TypeSynReply = 0x0002
- TypeRstStream = 0x0003
- TypeSettings = 0x0004
- TypeNoop = 0x0005
- TypePing = 0x0006
- TypeGoAway = 0x0007
- TypeHeaders = 0x0008
- TypeWindowUpdate = 0x0009
-)
-
-// ControlFlags are the flags that can be set on a control frame.
-type ControlFlags uint8
-
-const (
- ControlFlagFin ControlFlags = 0x01
-)
-
-// DataFlags are the flags that can be set on a data frame.
-type DataFlags uint8
-
-const (
- DataFlagFin DataFlags = 0x01
- DataFlagCompressed = 0x02
-)
-
-// MaxDataLength is the maximum number of bytes that can be stored in one frame.
-const MaxDataLength = 1<<24 - 1
-
-// Frame is a single SPDY frame in its unpacked in-memory representation. Use
-// Framer to read and write it.
-type Frame interface {
- write(f *Framer) error
-}
-
-// ControlFrameHeader contains all the fields in a control frame header,
-// in its unpacked in-memory representation.
-type ControlFrameHeader struct {
- // Note, high bit is the "Control" bit.
- version uint16
- frameType ControlFrameType
- Flags ControlFlags
- length uint32
-}
-
-type controlFrame interface {
- Frame
- read(h ControlFrameHeader, f *Framer) error
-}
-
-// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM
-// frame.
-type SynStreamFrame struct {
- CFHeader ControlFrameHeader
- StreamId uint32
- AssociatedToStreamId uint32
- // Note, only 2 highest bits currently used
- // Rest of Priority is unused.
- Priority uint16
- Headers http.Header
-}
-
-// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame.
-type SynReplyFrame struct {
- CFHeader ControlFrameHeader
- StreamId uint32
- Headers http.Header
-}
-
-// StatusCode represents the status that led to a RST_STREAM
-type StatusCode uint32
-
-const (
- ProtocolError StatusCode = 1
- InvalidStream = 2
- RefusedStream = 3
- UnsupportedVersion = 4
- Cancel = 5
- InternalError = 6
- FlowControlError = 7
-)
-
-// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM
-// frame.
-type RstStreamFrame struct {
- CFHeader ControlFrameHeader
- StreamId uint32
- Status StatusCode
-}
-
-// SettingsFlag represents a flag in a SETTINGS frame.
-type SettingsFlag uint8
-
-const (
- FlagSettingsPersistValue SettingsFlag = 0x1
- FlagSettingsPersisted = 0x2
-)
-
-// SettingsFlag represents the id of an id/value pair in a SETTINGS frame.
-type SettingsId uint32
-
-const (
- SettingsUploadBandwidth SettingsId = 1
- SettingsDownloadBandwidth = 2
- SettingsRoundTripTime = 3
- SettingsMaxConcurrentStreams = 4
- SettingsCurrentCwnd = 5
-)
-
-// SettingsFlagIdValue is the unpacked, in-memory representation of the
-// combined flag/id/value for a setting in a SETTINGS frame.
-type SettingsFlagIdValue struct {
- Flag SettingsFlag
- Id SettingsId
- Value uint32
-}
-
-// SettingsFrame is the unpacked, in-memory representation of a SPDY
-// SETTINGS frame.
-type SettingsFrame struct {
- CFHeader ControlFrameHeader
- FlagIdValues []SettingsFlagIdValue
-}
-
-// NoopFrame is the unpacked, in-memory representation of a NOOP frame.
-type NoopFrame struct {
- CFHeader ControlFrameHeader
-}
-
-// PingFrame is the unpacked, in-memory representation of a PING frame.
-type PingFrame struct {
- CFHeader ControlFrameHeader
- Id uint32
-}
-
-// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame.
-type GoAwayFrame struct {
- CFHeader ControlFrameHeader
- LastGoodStreamId uint32
-}
-
-// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame.
-type HeadersFrame struct {
- CFHeader ControlFrameHeader
- StreamId uint32
- Headers http.Header
-}
-
-// DataFrame is the unpacked, in-memory representation of a DATA frame.
-type DataFrame struct {
- // Note, high bit is the "Control" bit. Should be 0 for data frames.
- StreamId uint32
- Flags DataFlags
- Data []byte
-}
-
-// HeaderDictionary is the dictionary sent to the zlib compressor/decompressor.
-// Even though the specification states there is no null byte at the end, Chrome sends it.
-const HeaderDictionary = "optionsgetheadpostputdeletetrace" +
- "acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" +
- "if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" +
- "max-forwardsproxy-authorizationrangerefererteuser-agent" +
- "100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" +
- "accept-rangesageetaglocationproxy-authenticatepublicretry-after" +
- "servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" +
- "connectiondatetrailertransfer-encodingupgradeviawarning" +
- "content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" +
- "MondayTuesdayWednesdayThursdayFridaySaturdaySunday" +
- "JanFebMarAprMayJunJulAugSepOctNovDec" +
- "chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" +
- "charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00"
-
-// A SPDY specific error.
-type ErrorCode string
-
-const (
- UnlowercasedHeaderName ErrorCode = "header was not lowercased"
- DuplicateHeaders ErrorCode = "multiple headers with same name"
- WrongCompressedPayloadSize ErrorCode = "compressed payload size was incorrect"
- UnknownFrameType ErrorCode = "unknown frame type"
- InvalidControlFrame ErrorCode = "invalid control frame"
- InvalidDataFrame ErrorCode = "invalid data frame"
- InvalidHeaderPresent ErrorCode = "frame contained invalid header"
-)
-
-// Error contains both the type of error and additional values. StreamId is 0
-// if Error is not associated with a stream.
-type Error struct {
- Err ErrorCode
- StreamId uint32
-}
-
-func (e *Error) Error() string {
- return string(e.Err)
-}
-
-var invalidReqHeaders = map[string]bool{
- "Connection": true,
- "Keep-Alive": true,
- "Proxy-Connection": true,
- "Transfer-Encoding": true,
-}
-
-var invalidRespHeaders = map[string]bool{
- "Connection": true,
- "Keep-Alive": true,
- "Transfer-Encoding": true,
-}
-
-// Framer handles serializing/deserializing SPDY frames, including compressing/
-// decompressing payloads.
-type Framer struct {
- headerCompressionDisabled bool
- w io.Writer
- headerBuf *bytes.Buffer
- headerCompressor *zlib.Writer
- r io.Reader
- headerReader io.LimitedReader
- headerDecompressor io.ReadCloser
-}
-
-// NewFramer allocates a new Framer for a given SPDY connection, repesented by
-// a io.Writer and io.Reader. Note that Framer will read and write individual fields
-// from/to the Reader and Writer, so the caller should pass in an appropriately
-// buffered implementation to optimize performance.
-func NewFramer(w io.Writer, r io.Reader) (*Framer, error) {
- compressBuf := new(bytes.Buffer)
- compressor, err := zlib.NewWriterDict(compressBuf, zlib.BestCompression, []byte(HeaderDictionary))
- if err != nil {
- return nil, err
- }
- framer := &Framer{
- w: w,
- headerBuf: compressBuf,
- headerCompressor: compressor,
- r: r,
- }
- return framer, nil
-}
diff --git a/libgo/go/exp/spdy/write.go b/libgo/go/exp/spdy/write.go
deleted file mode 100644
index 3dd2ca1d5d8..00000000000
--- a/libgo/go/exp/spdy/write.go
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spdy
-
-import (
- "encoding/binary"
- "io"
- "net/http"
- "strings"
-)
-
-func (frame *SynStreamFrame) write(f *Framer) error {
- return f.writeSynStreamFrame(frame)
-}
-
-func (frame *SynReplyFrame) write(f *Framer) error {
- return f.writeSynReplyFrame(frame)
-}
-
-func (frame *RstStreamFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeRstStream
- frame.CFHeader.length = 8
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
- return
- }
- return
-}
-
-func (frame *SettingsFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeSettings
- frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
- return
- }
- for _, flagIdValue := range frame.FlagIdValues {
- flagId := (uint32(flagIdValue.Flag) << 24) | uint32(flagIdValue.Id)
- if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
- return
- }
- }
- return
-}
-
-func (frame *NoopFrame) write(f *Framer) error {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeNoop
-
- // Serialize frame to Writer
- return writeControlFrameHeader(f.w, frame.CFHeader)
-}
-
-func (frame *PingFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypePing
- frame.CFHeader.length = 4
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
- return
- }
- return
-}
-
-func (frame *GoAwayFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeGoAway
- frame.CFHeader.length = 4
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
- return
- }
- return nil
-}
-
-func (frame *HeadersFrame) write(f *Framer) error {
- return f.writeHeadersFrame(frame)
-}
-
-func (frame *DataFrame) write(f *Framer) error {
- return f.writeDataFrame(frame)
-}
-
-// WriteFrame writes a frame.
-func (f *Framer) WriteFrame(frame Frame) error {
- return frame.write(f)
-}
-
-func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
- if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
- return err
- }
- if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
- return err
- }
- flagsAndLength := (uint32(h.Flags) << 24) | h.length
- if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
- return err
- }
- return nil
-}
-
-func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
- n = 0
- if err = binary.Write(w, binary.BigEndian, uint16(len(h))); err != nil {
- return
- }
- n += 2
- for name, values := range h {
- if err = binary.Write(w, binary.BigEndian, uint16(len(name))); err != nil {
- return
- }
- n += 2
- name = strings.ToLower(name)
- if _, err = io.WriteString(w, name); err != nil {
- return
- }
- n += len(name)
- v := strings.Join(values, "\x00")
- if err = binary.Write(w, binary.BigEndian, uint16(len(v))); err != nil {
- return
- }
- n += 2
- if _, err = io.WriteString(w, v); err != nil {
- return
- }
- n += len(v)
- }
- return
-}
-
-func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
- // Marshal the headers.
- var writer io.Writer = f.headerBuf
- if !f.headerCompressionDisabled {
- writer = f.headerCompressor
- }
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
- return
- }
- if !f.headerCompressionDisabled {
- f.headerCompressor.Flush()
- }
-
- // Set ControlFrameHeader
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeSynStream
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<14); err != nil {
- return err
- }
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
- return err
- }
- f.headerBuf.Reset()
- return nil
-}
-
-func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
- // Marshal the headers.
- var writer io.Writer = f.headerBuf
- if !f.headerCompressionDisabled {
- writer = f.headerCompressor
- }
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
- return
- }
- if !f.headerCompressionDisabled {
- f.headerCompressor.Flush()
- }
-
- // Set ControlFrameHeader
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeSynReply
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
- return
- }
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
- return
- }
- f.headerBuf.Reset()
- return
-}
-
-func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
- // Marshal the headers.
- var writer io.Writer = f.headerBuf
- if !f.headerCompressionDisabled {
- writer = f.headerCompressor
- }
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
- return
- }
- if !f.headerCompressionDisabled {
- f.headerCompressor.Flush()
- }
-
- // Set ControlFrameHeader
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeHeaders
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
-
- // Serialize frame to Writer
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
- return
- }
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
- return
- }
- f.headerBuf.Reset()
- return
-}
-
-func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
- // Validate DataFrame
- if frame.StreamId&0x80000000 != 0 || len(frame.Data) >= 0x0f000000 {
- return &Error{InvalidDataFrame, frame.StreamId}
- }
-
- // Serialize frame to Writer
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- flagsAndLength := (uint32(frame.Flags) << 24) | uint32(len(frame.Data))
- if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
- return
- }
- if _, err = f.w.Write(frame.Data); err != nil {
- return
- }
-
- return nil
-}
diff --git a/libgo/go/exp/ssh/channel.go b/libgo/go/exp/ssh/channel.go
deleted file mode 100644
index 9d75f37de74..00000000000
--- a/libgo/go/exp/ssh/channel.go
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "errors"
- "io"
- "sync"
-)
-
-// A Channel is an ordered, reliable, duplex stream that is multiplexed over an
-// SSH connection.
-type Channel interface {
- // Accept accepts the channel creation request.
- Accept() error
- // Reject rejects the channel creation request. After calling this, no
- // other methods on the Channel may be called. If they are then the
- // peer is likely to signal a protocol error and drop the connection.
- Reject(reason RejectionReason, message string) error
-
- // Read may return a ChannelRequest as an error.
- Read(data []byte) (int, error)
- Write(data []byte) (int, error)
- Close() error
-
- // AckRequest either sends an ack or nack to the channel request.
- AckRequest(ok bool) error
-
- // ChannelType returns the type of the channel, as supplied by the
- // client.
- ChannelType() string
- // ExtraData returns the arbitary payload for this channel, as supplied
- // by the client. This data is specific to the channel type.
- ExtraData() []byte
-}
-
-// ChannelRequest represents a request sent on a channel, outside of the normal
-// stream of bytes. It may result from calling Read on a Channel.
-type ChannelRequest struct {
- Request string
- WantReply bool
- Payload []byte
-}
-
-func (c ChannelRequest) Error() string {
- return "channel request received"
-}
-
-// RejectionReason is an enumeration used when rejecting channel creation
-// requests. See RFC 4254, section 5.1.
-type RejectionReason int
-
-const (
- Prohibited RejectionReason = iota + 1
- ConnectionFailed
- UnknownChannelType
- ResourceShortage
-)
-
-type channel struct {
- // immutable once created
- chanType string
- extraData []byte
-
- theyClosed bool
- theySentEOF bool
- weClosed bool
- dead bool
-
- serverConn *ServerConn
- myId, theirId uint32
- myWindow, theirWindow uint32
- maxPacketSize uint32
- err error
-
- pendingRequests []ChannelRequest
- pendingData []byte
- head, length int
-
- // This lock is inferior to serverConn.lock
- lock sync.Mutex
- cond *sync.Cond
-}
-
-func (c *channel) Accept() error {
- c.serverConn.lock.Lock()
- defer c.serverConn.lock.Unlock()
-
- if c.serverConn.err != nil {
- return c.serverConn.err
- }
-
- confirm := channelOpenConfirmMsg{
- PeersId: c.theirId,
- MyId: c.myId,
- MyWindow: c.myWindow,
- MaxPacketSize: c.maxPacketSize,
- }
- return c.serverConn.writePacket(marshal(msgChannelOpenConfirm, confirm))
-}
-
-func (c *channel) Reject(reason RejectionReason, message string) error {
- c.serverConn.lock.Lock()
- defer c.serverConn.lock.Unlock()
-
- if c.serverConn.err != nil {
- return c.serverConn.err
- }
-
- reject := channelOpenFailureMsg{
- PeersId: c.theirId,
- Reason: uint32(reason),
- Message: message,
- Language: "en",
- }
- return c.serverConn.writePacket(marshal(msgChannelOpenFailure, reject))
-}
-
-func (c *channel) handlePacket(packet interface{}) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- switch packet := packet.(type) {
- case *channelRequestMsg:
- req := ChannelRequest{
- Request: packet.Request,
- WantReply: packet.WantReply,
- Payload: packet.RequestSpecificData,
- }
-
- c.pendingRequests = append(c.pendingRequests, req)
- c.cond.Signal()
- case *channelCloseMsg:
- c.theyClosed = true
- c.cond.Signal()
- case *channelEOFMsg:
- c.theySentEOF = true
- c.cond.Signal()
- default:
- panic("unknown packet type")
- }
-}
-
-func (c *channel) handleData(data []byte) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- // The other side should never send us more than our window.
- if len(data)+c.length > len(c.pendingData) {
- // TODO(agl): we should tear down the channel with a protocol
- // error.
- return
- }
-
- c.myWindow -= uint32(len(data))
- for i := 0; i < 2; i++ {
- tail := c.head + c.length
- if tail > len(c.pendingData) {
- tail -= len(c.pendingData)
- }
- n := copy(c.pendingData[tail:], data)
- data = data[n:]
- c.length += n
- }
-
- c.cond.Signal()
-}
-
-func (c *channel) Read(data []byte) (n int, err error) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- if c.err != nil {
- return 0, c.err
- }
-
- if c.myWindow <= uint32(len(c.pendingData))/2 {
- packet := marshal(msgChannelWindowAdjust, windowAdjustMsg{
- PeersId: c.theirId,
- AdditionalBytes: uint32(len(c.pendingData)) - c.myWindow,
- })
- if err := c.serverConn.writePacket(packet); err != nil {
- return 0, err
- }
- }
-
- for {
- if c.theySentEOF || c.theyClosed || c.dead {
- return 0, io.EOF
- }
-
- if len(c.pendingRequests) > 0 {
- req := c.pendingRequests[0]
- if len(c.pendingRequests) == 1 {
- c.pendingRequests = nil
- } else {
- oldPendingRequests := c.pendingRequests
- c.pendingRequests = make([]ChannelRequest, len(oldPendingRequests)-1)
- copy(c.pendingRequests, oldPendingRequests[1:])
- }
-
- return 0, req
- }
-
- if c.length > 0 {
- tail := c.head + c.length
- if tail > len(c.pendingData) {
- tail -= len(c.pendingData)
- }
- n = copy(data, c.pendingData[c.head:tail])
- c.head += n
- c.length -= n
- if c.head == len(c.pendingData) {
- c.head = 0
- }
- return
- }
-
- c.cond.Wait()
- }
-
- panic("unreachable")
-}
-
-func (c *channel) Write(data []byte) (n int, err error) {
- for len(data) > 0 {
- c.lock.Lock()
- if c.dead || c.weClosed {
- return 0, io.EOF
- }
-
- if c.theirWindow == 0 {
- c.cond.Wait()
- continue
- }
- c.lock.Unlock()
-
- todo := data
- if uint32(len(todo)) > c.theirWindow {
- todo = todo[:c.theirWindow]
- }
-
- packet := make([]byte, 1+4+4+len(todo))
- packet[0] = msgChannelData
- packet[1] = byte(c.theirId >> 24)
- packet[2] = byte(c.theirId >> 16)
- packet[3] = byte(c.theirId >> 8)
- packet[4] = byte(c.theirId)
- packet[5] = byte(len(todo) >> 24)
- packet[6] = byte(len(todo) >> 16)
- packet[7] = byte(len(todo) >> 8)
- packet[8] = byte(len(todo))
- copy(packet[9:], todo)
-
- c.serverConn.lock.Lock()
- if err = c.serverConn.writePacket(packet); err != nil {
- c.serverConn.lock.Unlock()
- return
- }
- c.serverConn.lock.Unlock()
-
- n += len(todo)
- data = data[len(todo):]
- }
-
- return
-}
-
-func (c *channel) Close() error {
- c.serverConn.lock.Lock()
- defer c.serverConn.lock.Unlock()
-
- if c.serverConn.err != nil {
- return c.serverConn.err
- }
-
- if c.weClosed {
- return errors.New("ssh: channel already closed")
- }
- c.weClosed = true
-
- closeMsg := channelCloseMsg{
- PeersId: c.theirId,
- }
- return c.serverConn.writePacket(marshal(msgChannelClose, closeMsg))
-}
-
-func (c *channel) AckRequest(ok bool) error {
- c.serverConn.lock.Lock()
- defer c.serverConn.lock.Unlock()
-
- if c.serverConn.err != nil {
- return c.serverConn.err
- }
-
- if ok {
- ack := channelRequestSuccessMsg{
- PeersId: c.theirId,
- }
- return c.serverConn.writePacket(marshal(msgChannelSuccess, ack))
- } else {
- ack := channelRequestFailureMsg{
- PeersId: c.theirId,
- }
- return c.serverConn.writePacket(marshal(msgChannelFailure, ack))
- }
- panic("unreachable")
-}
-
-func (c *channel) ChannelType() string {
- return c.chanType
-}
-
-func (c *channel) ExtraData() []byte {
- return c.extraData
-}
diff --git a/libgo/go/exp/ssh/cipher.go b/libgo/go/exp/ssh/cipher.go
deleted file mode 100644
index d91929aa99a..00000000000
--- a/libgo/go/exp/ssh/cipher.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/rc4"
-)
-
-// streamDump is used to dump the initial keystream for stream ciphers. It is a
-// a write-only buffer, and not intended for reading so do not require a mutex.
-var streamDump [512]byte
-
-// noneCipher implements cipher.Stream and provides no encryption. It is used
-// by the transport before the first key-exchange.
-type noneCipher struct{}
-
-func (c noneCipher) XORKeyStream(dst, src []byte) {
- copy(dst, src)
-}
-
-func newAESCTR(key, iv []byte) (cipher.Stream, error) {
- c, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- return cipher.NewCTR(c, iv), nil
-}
-
-func newRC4(key, iv []byte) (cipher.Stream, error) {
- return rc4.NewCipher(key)
-}
-
-type cipherMode struct {
- keySize int
- ivSize int
- skip int
- createFn func(key, iv []byte) (cipher.Stream, error)
-}
-
-func (c *cipherMode) createCipher(key, iv []byte) (cipher.Stream, error) {
- if len(key) < c.keySize {
- panic("ssh: key length too small for cipher")
- }
- if len(iv) < c.ivSize {
- panic("ssh: iv too small for cipher")
- }
-
- stream, err := c.createFn(key[:c.keySize], iv[:c.ivSize])
- if err != nil {
- return nil, err
- }
-
- for remainingToDump := c.skip; remainingToDump > 0; {
- dumpThisTime := remainingToDump
- if dumpThisTime > len(streamDump) {
- dumpThisTime = len(streamDump)
- }
- stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
- remainingToDump -= dumpThisTime
- }
-
- return stream, nil
-}
-
-// Specifies a default set of ciphers and a preference order. This is based on
-// OpenSSH's default client preference order, minus algorithms that are not
-// implemented.
-var DefaultCipherOrder = []string{
- "aes128-ctr", "aes192-ctr", "aes256-ctr",
- "arcfour256", "arcfour128",
-}
-
-var cipherModes = map[string]*cipherMode{
- // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
- // are defined in the order specified in the RFC.
- "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
- "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
- "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
-
- // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
- // They are defined in the order specified in the RFC.
- "arcfour128": {16, 0, 1536, newRC4},
- "arcfour256": {32, 0, 1536, newRC4},
-}
diff --git a/libgo/go/exp/ssh/cipher_test.go b/libgo/go/exp/ssh/cipher_test.go
deleted file mode 100644
index ea27bd8a803..00000000000
--- a/libgo/go/exp/ssh/cipher_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "bytes"
- "testing"
-)
-
-// TestCipherReversal tests that each cipher factory produces ciphers that can
-// encrypt and decrypt some data successfully.
-func TestCipherReversal(t *testing.T) {
- testData := []byte("abcdefghijklmnopqrstuvwxyz012345")
- testKey := []byte("AbCdEfGhIjKlMnOpQrStUvWxYz012345")
- testIv := []byte("sdflkjhsadflkjhasdflkjhsadfklhsa")
-
- cryptBuffer := make([]byte, 32)
-
- for name, cipherMode := range cipherModes {
- encrypter, err := cipherMode.createCipher(testKey, testIv)
- if err != nil {
- t.Errorf("failed to create encrypter for %q: %s", name, err)
- continue
- }
- decrypter, err := cipherMode.createCipher(testKey, testIv)
- if err != nil {
- t.Errorf("failed to create decrypter for %q: %s", name, err)
- continue
- }
-
- copy(cryptBuffer, testData)
-
- encrypter.XORKeyStream(cryptBuffer, cryptBuffer)
- if name == "none" {
- if !bytes.Equal(cryptBuffer, testData) {
- t.Errorf("encryption made change with 'none' cipher")
- continue
- }
- } else {
- if bytes.Equal(cryptBuffer, testData) {
- t.Errorf("encryption made no change with %q", name)
- continue
- }
- }
-
- decrypter.XORKeyStream(cryptBuffer, cryptBuffer)
- if !bytes.Equal(cryptBuffer, testData) {
- t.Errorf("decrypted bytes not equal to input with %q", name)
- continue
- }
- }
-}
-
-func TestDefaultCiphersExist(t *testing.T) {
- for _, cipherAlgo := range DefaultCipherOrder {
- if _, ok := cipherModes[cipherAlgo]; !ok {
- t.Errorf("default cipher %q is unknown", cipherAlgo)
- }
- }
-}
diff --git a/libgo/go/exp/ssh/client.go b/libgo/go/exp/ssh/client.go
deleted file mode 100644
index eb6c0352210..00000000000
--- a/libgo/go/exp/ssh/client.go
+++ /dev/null
@@ -1,505 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "crypto"
- "crypto/rand"
- "errors"
- "fmt"
- "io"
- "math/big"
- "net"
- "sync"
-)
-
-// clientVersion is the fixed identification string that the client will use.
-var clientVersion = []byte("SSH-2.0-Go\r\n")
-
-// ClientConn represents the client side of an SSH connection.
-type ClientConn struct {
- *transport
- config *ClientConfig
- chanlist
-}
-
-// Client returns a new SSH client connection using c as the underlying transport.
-func Client(c net.Conn, config *ClientConfig) (*ClientConn, error) {
- conn := &ClientConn{
- transport: newTransport(c, config.rand()),
- config: config,
- }
- if err := conn.handshake(); err != nil {
- conn.Close()
- return nil, err
- }
- go conn.mainLoop()
- return conn, nil
-}
-
-// handshake performs the client side key exchange. See RFC 4253 Section 7.
-func (c *ClientConn) handshake() error {
- var magics handshakeMagics
-
- if _, err := c.Write(clientVersion); err != nil {
- return err
- }
- if err := c.Flush(); err != nil {
- return err
- }
- magics.clientVersion = clientVersion[:len(clientVersion)-2]
-
- // read remote server version
- version, err := readVersion(c)
- if err != nil {
- return err
- }
- magics.serverVersion = version
- clientKexInit := kexInitMsg{
- KexAlgos: supportedKexAlgos,
- ServerHostKeyAlgos: supportedHostKeyAlgos,
- CiphersClientServer: c.config.Crypto.ciphers(),
- CiphersServerClient: c.config.Crypto.ciphers(),
- MACsClientServer: supportedMACs,
- MACsServerClient: supportedMACs,
- CompressionClientServer: supportedCompressions,
- CompressionServerClient: supportedCompressions,
- }
- kexInitPacket := marshal(msgKexInit, clientKexInit)
- magics.clientKexInit = kexInitPacket
-
- if err := c.writePacket(kexInitPacket); err != nil {
- return err
- }
- packet, err := c.readPacket()
- if err != nil {
- return err
- }
-
- magics.serverKexInit = packet
-
- var serverKexInit kexInitMsg
- if err = unmarshal(&serverKexInit, packet, msgKexInit); err != nil {
- return err
- }
-
- kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(c.transport, &clientKexInit, &serverKexInit)
- if !ok {
- return errors.New("ssh: no common algorithms")
- }
-
- if serverKexInit.FirstKexFollows && kexAlgo != serverKexInit.KexAlgos[0] {
- // The server sent a Kex message for the wrong algorithm,
- // which we have to ignore.
- if _, err := c.readPacket(); err != nil {
- return err
- }
- }
-
- var H, K []byte
- var hashFunc crypto.Hash
- switch kexAlgo {
- case kexAlgoDH14SHA1:
- hashFunc = crypto.SHA1
- dhGroup14Once.Do(initDHGroup14)
- H, K, err = c.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo)
- default:
- err = fmt.Errorf("ssh: unexpected key exchange algorithm %v", kexAlgo)
- }
- if err != nil {
- return err
- }
-
- if err = c.writePacket([]byte{msgNewKeys}); err != nil {
- return err
- }
- if err = c.transport.writer.setupKeys(clientKeys, K, H, H, hashFunc); err != nil {
- return err
- }
- if packet, err = c.readPacket(); err != nil {
- return err
- }
- if packet[0] != msgNewKeys {
- return UnexpectedMessageError{msgNewKeys, packet[0]}
- }
- if err := c.transport.reader.setupKeys(serverKeys, K, H, H, hashFunc); err != nil {
- return err
- }
- return c.authenticate(H)
-}
-
-// kexDH performs Diffie-Hellman key agreement on a ClientConn. The
-// returned values are given the same names as in RFC 4253, section 8.
-func (c *ClientConn) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) ([]byte, []byte, error) {
- x, err := rand.Int(c.config.rand(), group.p)
- if err != nil {
- return nil, nil, err
- }
- X := new(big.Int).Exp(group.g, x, group.p)
- kexDHInit := kexDHInitMsg{
- X: X,
- }
- if err := c.writePacket(marshal(msgKexDHInit, kexDHInit)); err != nil {
- return nil, nil, err
- }
-
- packet, err := c.readPacket()
- if err != nil {
- return nil, nil, err
- }
-
- var kexDHReply = new(kexDHReplyMsg)
- if err = unmarshal(kexDHReply, packet, msgKexDHReply); err != nil {
- return nil, nil, err
- }
-
- if kexDHReply.Y.Sign() == 0 || kexDHReply.Y.Cmp(group.p) >= 0 {
- return nil, nil, errors.New("server DH parameter out of bounds")
- }
-
- kInt := new(big.Int).Exp(kexDHReply.Y, x, group.p)
- h := hashFunc.New()
- writeString(h, magics.clientVersion)
- writeString(h, magics.serverVersion)
- writeString(h, magics.clientKexInit)
- writeString(h, magics.serverKexInit)
- writeString(h, kexDHReply.HostKey)
- writeInt(h, X)
- writeInt(h, kexDHReply.Y)
- K := make([]byte, intLength(kInt))
- marshalInt(K, kInt)
- h.Write(K)
-
- H := h.Sum(nil)
-
- return H, K, nil
-}
-
-// mainLoop reads incoming messages and routes channel messages
-// to their respective ClientChans.
-func (c *ClientConn) mainLoop() {
- // TODO(dfc) signal the underlying close to all channels
- defer c.Close()
- for {
- packet, err := c.readPacket()
- if err != nil {
- break
- }
- // TODO(dfc) A note on blocking channel use.
- // The msg, win, data and dataExt channels of a clientChan can
- // cause this loop to block indefinately if the consumer does
- // not service them.
- switch packet[0] {
- case msgChannelData:
- if len(packet) < 9 {
- // malformed data packet
- break
- }
- peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
- if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
- packet = packet[9:]
- c.getChan(peersId).stdout.handleData(packet[:length])
- }
- case msgChannelExtendedData:
- if len(packet) < 13 {
- // malformed data packet
- break
- }
- peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
- datatype := uint32(packet[5])<<24 | uint32(packet[6])<<16 | uint32(packet[7])<<8 | uint32(packet[8])
- if length := int(packet[9])<<24 | int(packet[10])<<16 | int(packet[11])<<8 | int(packet[12]); length > 0 {
- packet = packet[13:]
- // RFC 4254 5.2 defines data_type_code 1 to be data destined
- // for stderr on interactive sessions. Other data types are
- // silently discarded.
- if datatype == 1 {
- c.getChan(peersId).stderr.handleData(packet[:length])
- }
- }
- default:
- switch msg := decode(packet).(type) {
- case *channelOpenMsg:
- c.getChan(msg.PeersId).msg <- msg
- case *channelOpenConfirmMsg:
- c.getChan(msg.PeersId).msg <- msg
- case *channelOpenFailureMsg:
- c.getChan(msg.PeersId).msg <- msg
- case *channelCloseMsg:
- ch := c.getChan(msg.PeersId)
- ch.theyClosed = true
- close(ch.stdin.win)
- ch.stdout.eof()
- ch.stderr.eof()
- close(ch.msg)
- if !ch.weClosed {
- ch.weClosed = true
- ch.sendClose()
- }
- c.chanlist.remove(msg.PeersId)
- case *channelEOFMsg:
- ch := c.getChan(msg.PeersId)
- ch.stdout.eof()
- // RFC 4254 is mute on how EOF affects dataExt messages but
- // it is logical to signal EOF at the same time.
- ch.stderr.eof()
- case *channelRequestSuccessMsg:
- c.getChan(msg.PeersId).msg <- msg
- case *channelRequestFailureMsg:
- c.getChan(msg.PeersId).msg <- msg
- case *channelRequestMsg:
- c.getChan(msg.PeersId).msg <- msg
- case *windowAdjustMsg:
- c.getChan(msg.PeersId).stdin.win <- int(msg.AdditionalBytes)
- case *disconnectMsg:
- break
- default:
- fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg)
- }
- }
- }
-}
-
-// Dial connects to the given network address using net.Dial and
-// then initiates a SSH handshake, returning the resulting client connection.
-func Dial(network, addr string, config *ClientConfig) (*ClientConn, error) {
- conn, err := net.Dial(network, addr)
- if err != nil {
- return nil, err
- }
- return Client(conn, config)
-}
-
-// A ClientConfig structure is used to configure a ClientConn. After one has
-// been passed to an SSH function it must not be modified.
-type ClientConfig struct {
- // Rand provides the source of entropy for key exchange. If Rand is
- // nil, the cryptographic random reader in package crypto/rand will
- // be used.
- Rand io.Reader
-
- // The username to authenticate.
- User string
-
- // A slice of ClientAuth methods. Only the first instance
- // of a particular RFC 4252 method will be used during authentication.
- Auth []ClientAuth
-
- // Cryptographic-related configuration.
- Crypto CryptoConfig
-}
-
-func (c *ClientConfig) rand() io.Reader {
- if c.Rand == nil {
- return rand.Reader
- }
- return c.Rand
-}
-
-// A clientChan represents a single RFC 4254 channel that is multiplexed
-// over a single SSH connection.
-type clientChan struct {
- packetWriter
- id, peersId uint32
- stdin *chanWriter // receives window adjustments
- stdout *chanReader // receives the payload of channelData messages
- stderr *chanReader // receives the payload of channelExtendedData messages
- msg chan interface{} // incoming messages
- theyClosed bool // indicates the close msg has been received from the remote side
- weClosed bool // incidates the close msg has been sent from our side
-}
-
-// newClientChan returns a partially constructed *clientChan
-// using the local id provided. To be usable clientChan.peersId
-// needs to be assigned once known.
-func newClientChan(t *transport, id uint32) *clientChan {
- c := &clientChan{
- packetWriter: t,
- id: id,
- msg: make(chan interface{}, 16),
- }
- c.stdin = &chanWriter{
- win: make(chan int, 16),
- clientChan: c,
- }
- c.stdout = &chanReader{
- data: make(chan []byte, 16),
- clientChan: c,
- }
- c.stderr = &chanReader{
- data: make(chan []byte, 16),
- clientChan: c,
- }
- return c
-}
-
-// waitForChannelOpenResponse, if successful, fills out
-// the peerId and records any initial window advertisement.
-func (c *clientChan) waitForChannelOpenResponse() error {
- switch msg := (<-c.msg).(type) {
- case *channelOpenConfirmMsg:
- // fixup peersId field
- c.peersId = msg.MyId
- c.stdin.win <- int(msg.MyWindow)
- return nil
- case *channelOpenFailureMsg:
- return errors.New(safeString(msg.Message))
- }
- return errors.New("unexpected packet")
-}
-
-// sendEOF sends EOF to the server. RFC 4254 Section 5.3
-func (c *clientChan) sendEOF() error {
- return c.writePacket(marshal(msgChannelEOF, channelEOFMsg{
- PeersId: c.peersId,
- }))
-}
-
-// sendClose signals the intent to close the channel.
-func (c *clientChan) sendClose() error {
- return c.writePacket(marshal(msgChannelClose, channelCloseMsg{
- PeersId: c.peersId,
- }))
-}
-
-// Close closes the channel. This does not close the underlying connection.
-func (c *clientChan) Close() error {
- if !c.weClosed {
- c.weClosed = true
- return c.sendClose()
- }
- return nil
-}
-
-// Thread safe channel list.
-type chanlist struct {
- // protects concurrent access to chans
- sync.Mutex
- // chans are indexed by the local id of the channel, clientChan.id.
- // The PeersId value of messages received by ClientConn.mainLoop is
- // used to locate the right local clientChan in this slice.
- chans []*clientChan
-}
-
-// Allocate a new ClientChan with the next avail local id.
-func (c *chanlist) newChan(t *transport) *clientChan {
- c.Lock()
- defer c.Unlock()
- for i := range c.chans {
- if c.chans[i] == nil {
- ch := newClientChan(t, uint32(i))
- c.chans[i] = ch
- return ch
- }
- }
- i := len(c.chans)
- ch := newClientChan(t, uint32(i))
- c.chans = append(c.chans, ch)
- return ch
-}
-
-func (c *chanlist) getChan(id uint32) *clientChan {
- c.Lock()
- defer c.Unlock()
- return c.chans[int(id)]
-}
-
-func (c *chanlist) remove(id uint32) {
- c.Lock()
- defer c.Unlock()
- c.chans[int(id)] = nil
-}
-
-// A chanWriter represents the stdin of a remote process.
-type chanWriter struct {
- win chan int // receives window adjustments
- rwin int // current rwin size
- clientChan *clientChan // the channel backing this writer
-}
-
-// Write writes data to the remote process's standard input.
-func (w *chanWriter) Write(data []byte) (written int, err error) {
- for len(data) > 0 {
- for w.rwin < 1 {
- win, ok := <-w.win
- if !ok {
- return 0, io.EOF
- }
- w.rwin += win
- }
- n := min(len(data), w.rwin)
- peersId := w.clientChan.peersId
- packet := []byte{
- msgChannelData,
- byte(peersId >> 24), byte(peersId >> 16), byte(peersId >> 8), byte(peersId),
- byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
- }
- if err = w.clientChan.writePacket(append(packet, data[:n]...)); err != nil {
- break
- }
- data = data[n:]
- w.rwin -= n
- written += n
- }
- return
-}
-
-func min(a, b int) int {
- if a < b {
- return a
- }
- return b
-}
-
-func (w *chanWriter) Close() error {
- return w.clientChan.sendEOF()
-}
-
-// A chanReader represents stdout or stderr of a remote process.
-type chanReader struct {
- // TODO(dfc) a fixed size channel may not be the right data structure.
- // If writes to this channel block, they will block mainLoop, making
- // it unable to receive new messages from the remote side.
- data chan []byte // receives data from remote
- dataClosed bool // protects data from being closed twice
- clientChan *clientChan // the channel backing this reader
- buf []byte
-}
-
-// eof signals to the consumer that there is no more data to be received.
-func (r *chanReader) eof() {
- if !r.dataClosed {
- r.dataClosed = true
- close(r.data)
- }
-}
-
-// handleData sends buf to the reader's consumer. If r.data is closed
-// the data will be silently discarded
-func (r *chanReader) handleData(buf []byte) {
- if !r.dataClosed {
- r.data <- buf
- }
-}
-
-// Read reads data from the remote process's stdout or stderr.
-func (r *chanReader) Read(data []byte) (int, error) {
- var ok bool
- for {
- if len(r.buf) > 0 {
- n := copy(data, r.buf)
- r.buf = r.buf[n:]
- msg := windowAdjustMsg{
- PeersId: r.clientChan.peersId,
- AdditionalBytes: uint32(n),
- }
- return n, r.clientChan.writePacket(marshal(msgChannelWindowAdjust, msg))
- }
- r.buf, ok = <-r.data
- if !ok {
- return 0, io.EOF
- }
- }
- panic("unreachable")
-}
diff --git a/libgo/go/exp/ssh/client_auth.go b/libgo/go/exp/ssh/client_auth.go
deleted file mode 100644
index 3a7e9fb9801..00000000000
--- a/libgo/go/exp/ssh/client_auth.go
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "errors"
- "io"
-)
-
-// authenticate authenticates with the remote server. See RFC 4252.
-func (c *ClientConn) authenticate(session []byte) error {
- // initiate user auth session
- if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
- return err
- }
- packet, err := c.readPacket()
- if err != nil {
- return err
- }
- var serviceAccept serviceAcceptMsg
- if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
- return err
- }
- // during the authentication phase the client first attempts the "none" method
- // then any untried methods suggested by the server.
- tried, remain := make(map[string]bool), make(map[string]bool)
- for auth := ClientAuth(new(noneAuth)); auth != nil; {
- ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
- if err != nil {
- return err
- }
- if ok {
- // success
- return nil
- }
- tried[auth.method()] = true
- delete(remain, auth.method())
- for _, meth := range methods {
- if tried[meth] {
- // if we've tried meth already, skip it.
- continue
- }
- remain[meth] = true
- }
- auth = nil
- for _, a := range c.config.Auth {
- if remain[a.method()] {
- auth = a
- break
- }
- }
- }
- return errors.New("ssh: unable to authenticate, no supported methods remain")
-}
-
-// A ClientAuth represents an instance of an RFC 4252 authentication method.
-type ClientAuth interface {
- // auth authenticates user over transport t.
- // Returns true if authentication is successful.
- // If authentication is not successful, a []string of alternative
- // method names is returned.
- auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)
-
- // method returns the RFC 4252 method name.
- method() string
-}
-
-// "none" authentication, RFC 4252 section 5.2.
-type noneAuth int
-
-func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
- if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
- User: user,
- Service: serviceSSH,
- Method: "none",
- })); err != nil {
- return false, nil, err
- }
-
- return handleAuthResponse(t)
-}
-
-func (n *noneAuth) method() string {
- return "none"
-}
-
-// "password" authentication, RFC 4252 Section 8.
-type passwordAuth struct {
- ClientPassword
-}
-
-func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
- type passwordAuthMsg struct {
- User string
- Service string
- Method string
- Reply bool
- Password string
- }
-
- pw, err := p.Password(user)
- if err != nil {
- return false, nil, err
- }
-
- if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
- User: user,
- Service: serviceSSH,
- Method: "password",
- Reply: false,
- Password: pw,
- })); err != nil {
- return false, nil, err
- }
-
- return handleAuthResponse(t)
-}
-
-func (p *passwordAuth) method() string {
- return "password"
-}
-
-// A ClientPassword implements access to a client's passwords.
-type ClientPassword interface {
- // Password returns the password to use for user.
- Password(user string) (password string, err error)
-}
-
-// ClientAuthPassword returns a ClientAuth using password authentication.
-func ClientAuthPassword(impl ClientPassword) ClientAuth {
- return &passwordAuth{impl}
-}
-
-// ClientKeyring implements access to a client key ring.
-type ClientKeyring interface {
- // Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if
- // no key exists at i.
- Key(i int) (key interface{}, err error)
-
- // Sign returns a signature of the given data using the i'th key
- // and the supplied random source.
- Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
-}
-
-// "publickey" authentication, RFC 4252 Section 7.
-type publickeyAuth struct {
- ClientKeyring
-}
-
-type publickeyAuthMsg struct {
- User string
- Service string
- Method string
- // HasSig indicates to the reciver packet that the auth request is signed and
- // should be used for authentication of the request.
- HasSig bool
- Algoname string
- Pubkey string
- // Sig is defined as []byte so marshal will exclude it during validateKey
- Sig []byte `ssh:"rest"`
-}
-
-func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
-
- // Authentication is performed in two stages. The first stage sends an
- // enquiry to test if each key is acceptable to the remote. The second
- // stage attempts to authenticate with the valid keys obtained in the
- // first stage.
-
- var index int
- // a map of public keys to their index in the keyring
- validKeys := make(map[int]interface{})
- for {
- key, err := p.Key(index)
- if err != nil {
- return false, nil, err
- }
- if key == nil {
- // no more keys in the keyring
- break
- }
-
- if ok, err := p.validateKey(key, user, t); ok {
- validKeys[index] = key
- } else {
- if err != nil {
- return false, nil, err
- }
- }
- index++
- }
-
- // methods that may continue if this auth is not successful.
- var methods []string
- for i, key := range validKeys {
- pubkey := serializePublickey(key)
- algoname := algoName(key)
- sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
- User: user,
- Service: serviceSSH,
- Method: p.method(),
- }, []byte(algoname), pubkey))
- if err != nil {
- return false, nil, err
- }
- // manually wrap the serialized signature in a string
- s := serializeSignature(algoname, sign)
- sig := make([]byte, stringLength(s))
- marshalString(sig, s)
- msg := publickeyAuthMsg{
- User: user,
- Service: serviceSSH,
- Method: p.method(),
- HasSig: true,
- Algoname: algoname,
- Pubkey: string(pubkey),
- Sig: sig,
- }
- p := marshal(msgUserAuthRequest, msg)
- if err := t.writePacket(p); err != nil {
- return false, nil, err
- }
- success, methods, err := handleAuthResponse(t)
- if err != nil {
- return false, nil, err
- }
- if success {
- return success, methods, err
- }
- }
- return false, methods, nil
-}
-
-// validateKey validates the key provided it is acceptable to the server.
-func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
- pubkey := serializePublickey(key)
- algoname := algoName(key)
- msg := publickeyAuthMsg{
- User: user,
- Service: serviceSSH,
- Method: p.method(),
- HasSig: false,
- Algoname: algoname,
- Pubkey: string(pubkey),
- }
- if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
- return false, err
- }
-
- return p.confirmKeyAck(key, t)
-}
-
-func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
- pubkey := serializePublickey(key)
- algoname := algoName(key)
-
- for {
- packet, err := t.readPacket()
- if err != nil {
- return false, err
- }
- switch packet[0] {
- case msgUserAuthBanner:
- // TODO(gpaul): add callback to present the banner to the user
- case msgUserAuthPubKeyOk:
- msg := decode(packet).(*userAuthPubKeyOkMsg)
- if msg.Algo != algoname || msg.PubKey != string(pubkey) {
- return false, nil
- }
- return true, nil
- case msgUserAuthFailure:
- return false, nil
- default:
- return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
- }
- }
- panic("unreachable")
-}
-
-func (p *publickeyAuth) method() string {
- return "publickey"
-}
-
-// ClientAuthKeyring returns a ClientAuth using public key authentication.
-func ClientAuthKeyring(impl ClientKeyring) ClientAuth {
- return &publickeyAuth{impl}
-}
-
-// handleAuthResponse returns whether the preceding authentication request succeeded
-// along with a list of remaining authentication methods to try next and
-// an error if an unexpected response was received.
-func handleAuthResponse(t *transport) (bool, []string, error) {
- for {
- packet, err := t.readPacket()
- if err != nil {
- return false, nil, err
- }
-
- switch packet[0] {
- case msgUserAuthBanner:
- // TODO: add callback to present the banner to the user
- case msgUserAuthFailure:
- msg := decode(packet).(*userAuthFailureMsg)
- return false, msg.Methods, nil
- case msgUserAuthSuccess:
- return true, nil, nil
- case msgDisconnect:
- return false, nil, io.EOF
- default:
- return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
- }
- }
- panic("unreachable")
-}
diff --git a/libgo/go/exp/ssh/client_auth_test.go b/libgo/go/exp/ssh/client_auth_test.go
deleted file mode 100644
index c41a93b5c7d..00000000000
--- a/libgo/go/exp/ssh/client_auth_test.go
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "bytes"
- "crypto"
- "crypto/dsa"
- "crypto/rsa"
- _ "crypto/sha1"
- "crypto/x509"
- "encoding/pem"
- "errors"
- "io"
- "io/ioutil"
- "math/big"
- "testing"
-)
-
-// private key for mock server
-const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
-70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
-9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
-tupdMODN064vd3gyMKTwrlQ8tZM6aYuyOPsutLlUY7M5x5FwMDYvnPDSeyT/Iw0z
-s3B+NCyqeeMd2T7YzQFnRATj0M7rM5LoSs7DVqVriOEABssFyLj31PboaoLhOKgc
-qoM9khkNzr7FHVvi+DhYM2jD0DwvqZLN6NmnLwIDAQABAoIBAQCGVj+kuSFOV1lT
-+IclQYA6bM6uY5mroqcSBNegVxCNhWU03BxlW//BE9tA/+kq53vWylMeN9mpGZea
-riEMIh25KFGWXqXlOOioH8bkMsqA8S7sBmc7jljyv+0toQ9vCCtJ+sueNPhxQQxH
-D2YvUjfzBQ04I9+wn30BByDJ1QA/FoPsunxIOUCcRBE/7jxuLYcpR+JvEF68yYIh
-atXRld4W4in7T65YDR8jK1Uj9XAcNeDYNpT/M6oFLx1aPIlkG86aCWRO19S1jLPT
-b1ZAKHHxPMCVkSYW0RqvIgLXQOR62D0Zne6/2wtzJkk5UCjkSQ2z7ZzJpMkWgDgN
-ifCULFPBAoGBAPoMZ5q1w+zB+knXUD33n1J+niN6TZHJulpf2w5zsW+m2K6Zn62M
-MXndXlVAHtk6p02q9kxHdgov34Uo8VpuNjbS1+abGFTI8NZgFo+bsDxJdItemwC4
-KJ7L1iz39hRN/ZylMRLz5uTYRGddCkeIHhiG2h7zohH/MaYzUacXEEy3AoGBANz8
-e/msleB+iXC0cXKwds26N4hyMdAFE5qAqJXvV3S2W8JZnmU+sS7vPAWMYPlERPk1
-D8Q2eXqdPIkAWBhrx4RxD7rNc5qFNcQWEhCIxC9fccluH1y5g2M+4jpMX2CT8Uv+
-3z+NoJ5uDTXZTnLCfoZzgZ4nCZVZ+6iU5U1+YXFJAoGBANLPpIV920n/nJmmquMj
-orI1R/QXR9Cy56cMC65agezlGOfTYxk5Cfl5Ve+/2IJCfgzwJyjWUsFx7RviEeGw
-64o7JoUom1HX+5xxdHPsyZ96OoTJ5RqtKKoApnhRMamau0fWydH1yeOEJd+TRHhc
-XStGfhz8QNa1dVFvENczja1vAoGABGWhsd4VPVpHMc7lUvrf4kgKQtTC2PjA4xoc
-QJ96hf/642sVE76jl+N6tkGMzGjnVm4P2j+bOy1VvwQavKGoXqJBRd5Apppv727g
-/SM7hBXKFc/zH80xKBBgP/i1DR7kdjakCoeu4ngeGywvu2jTS6mQsqzkK+yWbUxJ
-I7mYBsECgYB/KNXlTEpXtz/kwWCHFSYA8U74l7zZbVD8ul0e56JDK+lLcJ0tJffk
-gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
-NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
------END RSA PRIVATE KEY-----`
-
-const testClientPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
-MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
-r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
-tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
-nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
-2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
-y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
-rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
------END RSA PRIVATE KEY-----`
-
-// keychain implements the ClientPublickey interface
-type keychain struct {
- keys []interface{}
-}
-
-func (k *keychain) Key(i int) (interface{}, error) {
- if i < 0 || i >= len(k.keys) {
- return nil, nil
- }
- switch key := k.keys[i].(type) {
- case *rsa.PrivateKey:
- return key.PublicKey, nil
- case *dsa.PrivateKey:
- return key.PublicKey, nil
- }
- panic("unknown key type")
-}
-
-func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
- hashFunc := crypto.SHA1
- h := hashFunc.New()
- h.Write(data)
- digest := h.Sum(nil)
- switch key := k.keys[i].(type) {
- case *rsa.PrivateKey:
- return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
- }
- return nil, errors.New("unknown key type")
-}
-
-func (k *keychain) loadPEM(file string) error {
- buf, err := ioutil.ReadFile(file)
- if err != nil {
- return err
- }
- block, _ := pem.Decode(buf)
- if block == nil {
- return errors.New("ssh: no key found")
- }
- r, err := x509.ParsePKCS1PrivateKey(block.Bytes)
- if err != nil {
- return err
- }
- k.keys = append(k.keys, r)
- return nil
-}
-
-// password implements the ClientPassword interface
-type password string
-
-func (p password) Password(user string) (string, error) {
- return string(p), nil
-}
-
-// reused internally by tests
-var (
- rsakey *rsa.PrivateKey
- dsakey *dsa.PrivateKey
- clientKeychain = new(keychain)
- clientPassword = password("tiger")
- serverConfig = &ServerConfig{
- PasswordCallback: func(user, pass string) bool {
- return user == "testuser" && pass == string(clientPassword)
- },
- PublicKeyCallback: func(user, algo string, pubkey []byte) bool {
- key := clientKeychain.keys[0].(*rsa.PrivateKey).PublicKey
- expected := []byte(serializePublickey(key))
- algoname := algoName(key)
- return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
- },
- }
-)
-
-func init() {
- if err := serverConfig.SetRSAPrivateKey([]byte(testServerPrivateKey)); err != nil {
- panic("unable to set private key: " + err.Error())
- }
-
- block, _ := pem.Decode([]byte(testClientPrivateKey))
- rsakey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
-
- clientKeychain.keys = append(clientKeychain.keys, rsakey)
- dsakey = new(dsa.PrivateKey)
- // taken from crypto/dsa/dsa_test.go
- dsakey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
- dsakey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
- dsakey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
- dsakey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
- dsakey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
-}
-
-// newMockAuthServer creates a new Server bound to
-// the loopback interface. The server exits after
-// processing one handshake.
-func newMockAuthServer(t *testing.T) string {
- l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
- if err != nil {
- t.Fatalf("unable to newMockAuthServer: %s", err)
- }
- go func() {
- defer l.Close()
- c, err := l.Accept()
- defer c.Close()
- if err != nil {
- t.Errorf("Unable to accept incoming connection: %v", err)
- return
- }
- if err := c.Handshake(); err != nil {
- // not Errorf because this is expected to
- // fail for some tests.
- t.Logf("Handshaking error: %v", err)
- return
- }
- }()
- return l.Addr().String()
-}
-
-func TestClientAuthPublickey(t *testing.T) {
- config := &ClientConfig{
- User: "testuser",
- Auth: []ClientAuth{
- ClientAuthKeyring(clientKeychain),
- },
- }
- c, err := Dial("tcp", newMockAuthServer(t), config)
- if err != nil {
- t.Fatalf("unable to dial remote side: %s", err)
- }
- c.Close()
-}
-
-func TestClientAuthPassword(t *testing.T) {
- config := &ClientConfig{
- User: "testuser",
- Auth: []ClientAuth{
- ClientAuthPassword(clientPassword),
- },
- }
-
- c, err := Dial("tcp", newMockAuthServer(t), config)
- if err != nil {
- t.Fatalf("unable to dial remote side: %s", err)
- }
- c.Close()
-}
-
-func TestClientAuthWrongPassword(t *testing.T) {
- wrongPw := password("wrong")
- config := &ClientConfig{
- User: "testuser",
- Auth: []ClientAuth{
- ClientAuthPassword(wrongPw),
- ClientAuthKeyring(clientKeychain),
- },
- }
-
- c, err := Dial("tcp", newMockAuthServer(t), config)
- if err != nil {
- t.Fatalf("unable to dial remote side: %s", err)
- }
- c.Close()
-}
-
-// the mock server will only authenticate ssh-rsa keys
-func TestClientAuthInvalidPublickey(t *testing.T) {
- kc := new(keychain)
- kc.keys = append(kc.keys, dsakey)
- config := &ClientConfig{
- User: "testuser",
- Auth: []ClientAuth{
- ClientAuthKeyring(kc),
- },
- }
-
- c, err := Dial("tcp", newMockAuthServer(t), config)
- if err == nil {
- c.Close()
- t.Fatalf("dsa private key should not have authenticated with rsa public key")
- }
-}
-
-// the client should authenticate with the second key
-func TestClientAuthRSAandDSA(t *testing.T) {
- kc := new(keychain)
- kc.keys = append(kc.keys, dsakey, rsakey)
- config := &ClientConfig{
- User: "testuser",
- Auth: []ClientAuth{
- ClientAuthKeyring(kc),
- },
- }
- c, err := Dial("tcp", newMockAuthServer(t), config)
- if err != nil {
- t.Fatalf("client could not authenticate with rsa key: %v", err)
- }
- c.Close()
-}
diff --git a/libgo/go/exp/ssh/client_func_test.go b/libgo/go/exp/ssh/client_func_test.go
deleted file mode 100644
index b4bdba95396..00000000000
--- a/libgo/go/exp/ssh/client_func_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-// ClientConn functional tests.
-// These tests require a running ssh server listening on port 22
-// on the local host. Functional tests will be skipped unless
-// -ssh.user and -ssh.pass must be passed to gotest.
-
-import (
- "flag"
- "testing"
-)
-
-var (
- sshuser = flag.String("ssh.user", "", "ssh username")
- sshpass = flag.String("ssh.pass", "", "ssh password")
- sshprivkey = flag.String("ssh.privkey", "", "ssh privkey file")
-)
-
-func TestFuncPasswordAuth(t *testing.T) {
- if *sshuser == "" {
- t.Log("ssh.user not defined, skipping test")
- return
- }
- config := &ClientConfig{
- User: *sshuser,
- Auth: []ClientAuth{
- ClientAuthPassword(password(*sshpass)),
- },
- }
- conn, err := Dial("tcp", "localhost:22", config)
- if err != nil {
- t.Fatalf("Unable to connect: %s", err)
- }
- defer conn.Close()
-}
-
-func TestFuncPublickeyAuth(t *testing.T) {
- if *sshuser == "" {
- t.Log("ssh.user not defined, skipping test")
- return
- }
- kc := new(keychain)
- if err := kc.loadPEM(*sshprivkey); err != nil {
- t.Fatalf("unable to load private key: %s", err)
- }
- config := &ClientConfig{
- User: *sshuser,
- Auth: []ClientAuth{
- ClientAuthKeyring(kc),
- },
- }
- conn, err := Dial("tcp", "localhost:22", config)
- if err != nil {
- t.Fatalf("unable to connect: %s", err)
- }
- defer conn.Close()
-}
diff --git a/libgo/go/exp/ssh/common.go b/libgo/go/exp/ssh/common.go
deleted file mode 100644
index 6844fb89b79..00000000000
--- a/libgo/go/exp/ssh/common.go
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "crypto/dsa"
- "crypto/rsa"
- "math/big"
- "strconv"
- "sync"
-)
-
-// These are string constants in the SSH protocol.
-const (
- kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
- hostAlgoRSA = "ssh-rsa"
- macSHA196 = "hmac-sha1-96"
- compressionNone = "none"
- serviceUserAuth = "ssh-userauth"
- serviceSSH = "ssh-connection"
-)
-
-var supportedKexAlgos = []string{kexAlgoDH14SHA1}
-var supportedHostKeyAlgos = []string{hostAlgoRSA}
-var supportedMACs = []string{macSHA196}
-var supportedCompressions = []string{compressionNone}
-
-// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
-type dhGroup struct {
- g, p *big.Int
-}
-
-// dhGroup14 is the group called diffie-hellman-group14-sha1 in RFC 4253 and
-// Oakley Group 14 in RFC 3526.
-var dhGroup14 *dhGroup
-
-var dhGroup14Once sync.Once
-
-func initDHGroup14() {
- p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
-
- dhGroup14 = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
- }
-}
-
-// UnexpectedMessageError results when the SSH message that we received didn't
-// match what we wanted.
-type UnexpectedMessageError struct {
- expected, got uint8
-}
-
-func (u UnexpectedMessageError) Error() string {
- return "ssh: unexpected message type " + strconv.Itoa(int(u.got)) + " (expected " + strconv.Itoa(int(u.expected)) + ")"
-}
-
-// ParseError results from a malformed SSH message.
-type ParseError struct {
- msgType uint8
-}
-
-func (p ParseError) Error() string {
- return "ssh: parse error in message type " + strconv.Itoa(int(p.msgType))
-}
-
-type handshakeMagics struct {
- clientVersion, serverVersion []byte
- clientKexInit, serverKexInit []byte
-}
-
-func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo string, ok bool) {
- for _, clientAlgo := range clientAlgos {
- for _, serverAlgo := range serverAlgos {
- if clientAlgo == serverAlgo {
- return clientAlgo, true
- }
- }
- }
-
- return
-}
-
-func findAgreedAlgorithms(transport *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) {
- kexAlgo, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos)
- if !ok {
- return
- }
-
- hostKeyAlgo, ok = findCommonAlgorithm(clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
- if !ok {
- return
- }
-
- transport.writer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
- if !ok {
- return
- }
-
- transport.reader.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
- if !ok {
- return
- }
-
- transport.writer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
- if !ok {
- return
- }
-
- transport.reader.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
- if !ok {
- return
- }
-
- transport.writer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
- if !ok {
- return
- }
-
- transport.reader.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
- if !ok {
- return
- }
-
- ok = true
- return
-}
-
-// Cryptographic configuration common to both ServerConfig and ClientConfig.
-type CryptoConfig struct {
- // The allowed cipher algorithms. If unspecified then DefaultCipherOrder is
- // used.
- Ciphers []string
-}
-
-func (c *CryptoConfig) ciphers() []string {
- if c.Ciphers == nil {
- return DefaultCipherOrder
- }
- return c.Ciphers
-}
-
-// serialize a signed slice according to RFC 4254 6.6.
-func serializeSignature(algoname string, sig []byte) []byte {
- length := stringLength([]byte(algoname))
- length += stringLength(sig)
-
- ret := make([]byte, length)
- r := marshalString(ret, []byte(algoname))
- r = marshalString(r, sig)
-
- return ret
-}
-
-// serialize an rsa.PublicKey or dsa.PublicKey according to RFC 4253 6.6.
-func serializePublickey(key interface{}) []byte {
- algoname := algoName(key)
- switch key := key.(type) {
- case rsa.PublicKey:
- e := new(big.Int).SetInt64(int64(key.E))
- length := stringLength([]byte(algoname))
- length += intLength(e)
- length += intLength(key.N)
- ret := make([]byte, length)
- r := marshalString(ret, []byte(algoname))
- r = marshalInt(r, e)
- marshalInt(r, key.N)
- return ret
- case dsa.PublicKey:
- length := stringLength([]byte(algoname))
- length += intLength(key.P)
- length += intLength(key.Q)
- length += intLength(key.G)
- length += intLength(key.Y)
- ret := make([]byte, length)
- r := marshalString(ret, []byte(algoname))
- r = marshalInt(r, key.P)
- r = marshalInt(r, key.Q)
- r = marshalInt(r, key.G)
- marshalInt(r, key.Y)
- return ret
- }
- panic("unexpected key type")
-}
-
-func algoName(key interface{}) string {
- switch key.(type) {
- case rsa.PublicKey:
- return "ssh-rsa"
- case dsa.PublicKey:
- return "ssh-dss"
- }
- panic("unexpected key type")
-}
-
-// buildDataSignedForAuth returns the data that is signed in order to prove
-// posession of a private key. See RFC 4252, section 7.
-func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
- user := []byte(req.User)
- service := []byte(req.Service)
- method := []byte(req.Method)
-
- length := stringLength(sessionId)
- length += 1
- length += stringLength(user)
- length += stringLength(service)
- length += stringLength(method)
- length += 1
- length += stringLength(algo)
- length += stringLength(pubKey)
-
- ret := make([]byte, length)
- r := marshalString(ret, sessionId)
- r[0] = msgUserAuthRequest
- r = r[1:]
- r = marshalString(r, user)
- r = marshalString(r, service)
- r = marshalString(r, method)
- r[0] = 1
- r = r[1:]
- r = marshalString(r, algo)
- r = marshalString(r, pubKey)
- return ret
-}
-
-// safeString sanitises s according to RFC 4251, section 9.2.
-// All control characters except tab, carriage return and newline are
-// replaced by 0x20.
-func safeString(s string) string {
- out := []byte(s)
- for i, c := range out {
- if c < 0x20 && c != 0xd && c != 0xa && c != 0x9 {
- out[i] = 0x20
- }
- }
- return string(out)
-}
diff --git a/libgo/go/exp/ssh/common_test.go b/libgo/go/exp/ssh/common_test.go
deleted file mode 100644
index 058fb04fe1b..00000000000
--- a/libgo/go/exp/ssh/common_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "testing"
-)
-
-func TestSafeString(t *testing.T) {
- strings := map[string]string{
- "\x20\x0d\x0a": "\x20\x0d\x0a",
- "flibble": "flibble",
- "new\x20line": "new\x20line",
- "123456\x07789": "123456 789",
- "\t\t\x10\r\n": "\t\t \r\n",
- }
-
- for s, expected := range strings {
- actual := safeString(s)
- if expected != actual {
- t.Errorf("expected: %v, actual: %v", []byte(expected), []byte(actual))
- }
- }
-}
diff --git a/libgo/go/exp/ssh/doc.go b/libgo/go/exp/ssh/doc.go
deleted file mode 100644
index e7deb5ec168..00000000000
--- a/libgo/go/exp/ssh/doc.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package ssh implements an SSH client and server.
-
-SSH is a transport security protocol, an authentication protocol and a
-family of application protocols. The most typical application level
-protocol is a remote shell and this is specifically implemented. However,
-the multiplexed nature of SSH is exposed to users that wish to support
-others.
-
-An SSH server is represented by a ServerConfig, which holds certificate
-details and handles authentication of ServerConns.
-
- config := new(ssh.ServerConfig)
- config.PubKeyCallback = pubKeyAuth
- config.PasswordCallback = passwordAuth
-
- pemBytes, err := ioutil.ReadFile("id_rsa")
- if err != nil {
- panic("Failed to load private key")
- }
- err = config.SetRSAPrivateKey(pemBytes)
- if err != nil {
- panic("Failed to parse private key")
- }
-
-Once a ServerConfig has been configured, connections can be accepted.
-
- listener := Listen("tcp", "0.0.0.0:2022", config)
- sConn, err := listener.Accept()
- if err != nil {
- panic("failed to accept incoming connection")
- }
- if err := sConn.Handshake(conn); err != nil {
- panic("failed to handshake")
- }
-
-An SSH connection multiplexes several channels, which must be accepted themselves:
-
- for {
- channel, err := sConn.Accept()
- if err != nil {
- panic("error from Accept")
- }
-
- ...
- }
-
-Accept reads from the connection, demultiplexes packets to their corresponding
-channels and returns when a new channel request is seen. Some goroutine must
-always be calling Accept; otherwise no messages will be forwarded to the
-channels.
-
-Channels have a type, depending on the application level protocol intended. In
-the case of a shell, the type is "session" and ServerShell may be used to
-present a simple terminal interface.
-
- if channel.ChannelType() != "session" {
- channel.Reject(UnknownChannelType, "unknown channel type")
- return
- }
- channel.Accept()
-
- term := terminal.NewTerminal(channel, "> ")
- serverTerm := &ssh.ServerTerminal{
- Term: term,
- Channel: channel,
- }
- go func() {
- defer channel.Close()
- for {
- line, err := serverTerm.ReadLine()
- if err != nil {
- break
- }
- println(line)
- }
- return
- }()
-
-To authenticate with the remote server you must pass at least one implementation of
-ClientAuth via the Auth field in ClientConfig.
-
- // password implements the ClientPassword interface
- type password string
-
- func (p password) Password(user string) (string, error) {
- return string(p), nil
- }
-
- config := &ssh.ClientConfig {
- User: "username",
- Auth: []ClientAuth {
- // ClientAuthPassword wraps a ClientPassword implementation
- // in a type that implements ClientAuth.
- ClientAuthPassword(password("yourpassword")),
- }
- }
-
-An SSH client is represented with a ClientConn. Currently only the "password"
-authentication method is supported.
-
- config := &ClientConfig{
- User: "username",
- Auth: []ClientAuth{ ... },
- }
- client, err := Dial("yourserver.com:22", config)
-
-Each ClientConn can support multiple interactive sessions, represented by a Session.
-
- session, err := client.NewSession()
-
-Once a Session is created, you can execute a single command on the remote side
-using the Exec method.
-
- b := bytes.NewBuffer()
- session.Stdin = b
- if err := session.Run("/usr/bin/whoami"); err != nil {
- panic("Failed to exec: " + err.String())
- }
- fmt.Println(bytes.String())
- session.Close()
-*/
-package ssh
diff --git a/libgo/go/exp/ssh/messages.go b/libgo/go/exp/ssh/messages.go
deleted file mode 100644
index 34ad131ff64..00000000000
--- a/libgo/go/exp/ssh/messages.go
+++ /dev/null
@@ -1,640 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "bytes"
- "io"
- "math/big"
- "reflect"
-)
-
-// These are SSH message type numbers. They are scattered around several
-// documents but many were taken from
-// http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
-const (
- msgDisconnect = 1
- msgIgnore = 2
- msgUnimplemented = 3
- msgDebug = 4
- msgServiceRequest = 5
- msgServiceAccept = 6
-
- msgKexInit = 20
- msgNewKeys = 21
-
- msgKexDHInit = 30
- msgKexDHReply = 31
-
- msgUserAuthRequest = 50
- msgUserAuthFailure = 51
- msgUserAuthSuccess = 52
- msgUserAuthBanner = 53
- msgUserAuthPubKeyOk = 60
-
- msgGlobalRequest = 80
- msgRequestSuccess = 81
- msgRequestFailure = 82
-
- msgChannelOpen = 90
- msgChannelOpenConfirm = 91
- msgChannelOpenFailure = 92
- msgChannelWindowAdjust = 93
- msgChannelData = 94
- msgChannelExtendedData = 95
- msgChannelEOF = 96
- msgChannelClose = 97
- msgChannelRequest = 98
- msgChannelSuccess = 99
- msgChannelFailure = 100
-)
-
-// SSH messages:
-//
-// These structures mirror the wire format of the corresponding SSH messages.
-// They are marshaled using reflection with the marshal and unmarshal functions
-// in this file. The only wrinkle is that a final member of type []byte with a
-// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
-
-// See RFC 4253, section 11.1.
-type disconnectMsg struct {
- Reason uint32
- Message string
- Language string
-}
-
-// See RFC 4253, section 7.1.
-type kexInitMsg struct {
- Cookie [16]byte
- KexAlgos []string
- ServerHostKeyAlgos []string
- CiphersClientServer []string
- CiphersServerClient []string
- MACsClientServer []string
- MACsServerClient []string
- CompressionClientServer []string
- CompressionServerClient []string
- LanguagesClientServer []string
- LanguagesServerClient []string
- FirstKexFollows bool
- Reserved uint32
-}
-
-// See RFC 4253, section 8.
-type kexDHInitMsg struct {
- X *big.Int
-}
-
-type kexDHReplyMsg struct {
- HostKey []byte
- Y *big.Int
- Signature []byte
-}
-
-// See RFC 4253, section 10.
-type serviceRequestMsg struct {
- Service string
-}
-
-// See RFC 4253, section 10.
-type serviceAcceptMsg struct {
- Service string
-}
-
-// See RFC 4252, section 5.
-type userAuthRequestMsg struct {
- User string
- Service string
- Method string
- Payload []byte `ssh:"rest"`
-}
-
-// See RFC 4252, section 5.1
-type userAuthFailureMsg struct {
- Methods []string
- PartialSuccess bool
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenMsg struct {
- ChanType string
- PeersId uint32
- PeersWindow uint32
- MaxPacketSize uint32
- TypeSpecificData []byte `ssh:"rest"`
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenConfirmMsg struct {
- PeersId uint32
- MyId uint32
- MyWindow uint32
- MaxPacketSize uint32
- TypeSpecificData []byte `ssh:"rest"`
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenFailureMsg struct {
- PeersId uint32
- Reason uint32
- Message string
- Language string
-}
-
-type channelRequestMsg struct {
- PeersId uint32
- Request string
- WantReply bool
- RequestSpecificData []byte `ssh:"rest"`
-}
-
-// See RFC 4254, section 5.4.
-type channelRequestSuccessMsg struct {
- PeersId uint32
-}
-
-// See RFC 4254, section 5.4.
-type channelRequestFailureMsg struct {
- PeersId uint32
-}
-
-// See RFC 4254, section 5.3
-type channelCloseMsg struct {
- PeersId uint32
-}
-
-// See RFC 4254, section 5.3
-type channelEOFMsg struct {
- PeersId uint32
-}
-
-// See RFC 4254, section 4
-type globalRequestMsg struct {
- Type string
- WantReply bool
-}
-
-// See RFC 4254, section 5.2
-type windowAdjustMsg struct {
- PeersId uint32
- AdditionalBytes uint32
-}
-
-// See RFC 4252, section 7
-type userAuthPubKeyOkMsg struct {
- Algo string
- PubKey string
-}
-
-// unmarshal parses the SSH wire data in packet into out using reflection.
-// expectedType is the expected SSH message type. It either returns nil on
-// success, or a ParseError or UnexpectedMessageError on error.
-func unmarshal(out interface{}, packet []byte, expectedType uint8) error {
- if len(packet) == 0 {
- return ParseError{expectedType}
- }
- if packet[0] != expectedType {
- return UnexpectedMessageError{expectedType, packet[0]}
- }
- packet = packet[1:]
-
- v := reflect.ValueOf(out).Elem()
- structType := v.Type()
- var ok bool
- for i := 0; i < v.NumField(); i++ {
- field := v.Field(i)
- t := field.Type()
- switch t.Kind() {
- case reflect.Bool:
- if len(packet) < 1 {
- return ParseError{expectedType}
- }
- field.SetBool(packet[0] != 0)
- packet = packet[1:]
- case reflect.Array:
- if t.Elem().Kind() != reflect.Uint8 {
- panic("array of non-uint8")
- }
- if len(packet) < t.Len() {
- return ParseError{expectedType}
- }
- for j := 0; j < t.Len(); j++ {
- field.Index(j).Set(reflect.ValueOf(packet[j]))
- }
- packet = packet[t.Len():]
- case reflect.Uint32:
- var u32 uint32
- if u32, packet, ok = parseUint32(packet); !ok {
- return ParseError{expectedType}
- }
- field.SetUint(uint64(u32))
- case reflect.String:
- var s []byte
- if s, packet, ok = parseString(packet); !ok {
- return ParseError{expectedType}
- }
- field.SetString(string(s))
- case reflect.Slice:
- switch t.Elem().Kind() {
- case reflect.Uint8:
- if structType.Field(i).Tag.Get("ssh") == "rest" {
- field.Set(reflect.ValueOf(packet))
- packet = nil
- } else {
- var s []byte
- if s, packet, ok = parseString(packet); !ok {
- return ParseError{expectedType}
- }
- field.Set(reflect.ValueOf(s))
- }
- case reflect.String:
- var nl []string
- if nl, packet, ok = parseNameList(packet); !ok {
- return ParseError{expectedType}
- }
- field.Set(reflect.ValueOf(nl))
- default:
- panic("slice of unknown type")
- }
- case reflect.Ptr:
- if t == bigIntType {
- var n *big.Int
- if n, packet, ok = parseInt(packet); !ok {
- return ParseError{expectedType}
- }
- field.Set(reflect.ValueOf(n))
- } else {
- panic("pointer to unknown type")
- }
- default:
- panic("unknown type")
- }
- }
-
- if len(packet) != 0 {
- return ParseError{expectedType}
- }
-
- return nil
-}
-
-// marshal serializes the message in msg, using the given message type.
-func marshal(msgType uint8, msg interface{}) []byte {
- var out []byte
- out = append(out, msgType)
-
- v := reflect.ValueOf(msg)
- structType := v.Type()
- for i := 0; i < v.NumField(); i++ {
- field := v.Field(i)
- t := field.Type()
- switch t.Kind() {
- case reflect.Bool:
- var v uint8
- if field.Bool() {
- v = 1
- }
- out = append(out, v)
- case reflect.Array:
- if t.Elem().Kind() != reflect.Uint8 {
- panic("array of non-uint8")
- }
- for j := 0; j < t.Len(); j++ {
- out = append(out, byte(field.Index(j).Uint()))
- }
- case reflect.Uint32:
- u32 := uint32(field.Uint())
- out = append(out, byte(u32>>24))
- out = append(out, byte(u32>>16))
- out = append(out, byte(u32>>8))
- out = append(out, byte(u32))
- case reflect.String:
- s := field.String()
- out = append(out, byte(len(s)>>24))
- out = append(out, byte(len(s)>>16))
- out = append(out, byte(len(s)>>8))
- out = append(out, byte(len(s)))
- out = append(out, s...)
- case reflect.Slice:
- switch t.Elem().Kind() {
- case reflect.Uint8:
- length := field.Len()
- if structType.Field(i).Tag.Get("ssh") != "rest" {
- out = append(out, byte(length>>24))
- out = append(out, byte(length>>16))
- out = append(out, byte(length>>8))
- out = append(out, byte(length))
- }
- for j := 0; j < length; j++ {
- out = append(out, byte(field.Index(j).Uint()))
- }
- case reflect.String:
- var length int
- for j := 0; j < field.Len(); j++ {
- if j != 0 {
- length++ /* comma */
- }
- length += len(field.Index(j).String())
- }
-
- out = append(out, byte(length>>24))
- out = append(out, byte(length>>16))
- out = append(out, byte(length>>8))
- out = append(out, byte(length))
- for j := 0; j < field.Len(); j++ {
- if j != 0 {
- out = append(out, ',')
- }
- out = append(out, field.Index(j).String()...)
- }
- default:
- panic("slice of unknown type")
- }
- case reflect.Ptr:
- if t == bigIntType {
- var n *big.Int
- nValue := reflect.ValueOf(&n)
- nValue.Elem().Set(field)
- needed := intLength(n)
- oldLength := len(out)
-
- if cap(out)-len(out) < needed {
- newOut := make([]byte, len(out), 2*(len(out)+needed))
- copy(newOut, out)
- out = newOut
- }
- out = out[:oldLength+needed]
- marshalInt(out[oldLength:], n)
- } else {
- panic("pointer to unknown type")
- }
- }
- }
-
- return out
-}
-
-var bigOne = big.NewInt(1)
-
-func parseString(in []byte) (out, rest []byte, ok bool) {
- if len(in) < 4 {
- return
- }
- length := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
- if uint32(len(in)) < 4+length {
- return
- }
- out = in[4 : 4+length]
- rest = in[4+length:]
- ok = true
- return
-}
-
-var (
- comma = []byte{','}
- emptyNameList = []string{}
-)
-
-func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
- contents, rest, ok := parseString(in)
- if !ok {
- return
- }
- if len(contents) == 0 {
- out = emptyNameList
- return
- }
- parts := bytes.Split(contents, comma)
- out = make([]string, len(parts))
- for i, part := range parts {
- out[i] = string(part)
- }
- return
-}
-
-func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
- contents, rest, ok := parseString(in)
- if !ok {
- return
- }
- out = new(big.Int)
-
- if len(contents) > 0 && contents[0]&0x80 == 0x80 {
- // This is a negative number
- notBytes := make([]byte, len(contents))
- for i := range notBytes {
- notBytes[i] = ^contents[i]
- }
- out.SetBytes(notBytes)
- out.Add(out, bigOne)
- out.Neg(out)
- } else {
- // Positive number
- out.SetBytes(contents)
- }
- ok = true
- return
-}
-
-func parseUint32(in []byte) (out uint32, rest []byte, ok bool) {
- if len(in) < 4 {
- return
- }
- out = uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
- rest = in[4:]
- ok = true
- return
-}
-
-func nameListLength(namelist []string) int {
- length := 4 /* uint32 length prefix */
- for i, name := range namelist {
- if i != 0 {
- length++ /* comma */
- }
- length += len(name)
- }
- return length
-}
-
-func intLength(n *big.Int) int {
- length := 4 /* length bytes */
- if n.Sign() < 0 {
- nMinus1 := new(big.Int).Neg(n)
- nMinus1.Sub(nMinus1, bigOne)
- bitLen := nMinus1.BitLen()
- if bitLen%8 == 0 {
- // The number will need 0xff padding
- length++
- }
- length += (bitLen + 7) / 8
- } else if n.Sign() == 0 {
- // A zero is the zero length string
- } else {
- bitLen := n.BitLen()
- if bitLen%8 == 0 {
- // The number will need 0x00 padding
- length++
- }
- length += (bitLen + 7) / 8
- }
-
- return length
-}
-
-func marshalUint32(to []byte, n uint32) []byte {
- to[0] = byte(n >> 24)
- to[1] = byte(n >> 16)
- to[2] = byte(n >> 8)
- to[3] = byte(n)
- return to[4:]
-}
-
-func marshalUint64(to []byte, n uint64) []byte {
- to[0] = byte(n >> 56)
- to[1] = byte(n >> 48)
- to[2] = byte(n >> 40)
- to[3] = byte(n >> 32)
- to[4] = byte(n >> 24)
- to[5] = byte(n >> 16)
- to[6] = byte(n >> 8)
- to[7] = byte(n)
- return to[8:]
-}
-
-func marshalInt(to []byte, n *big.Int) []byte {
- lengthBytes := to
- to = to[4:]
- length := 0
-
- if n.Sign() < 0 {
- // A negative number has to be converted to two's-complement
- // form. So we'll subtract 1 and invert. If the
- // most-significant-bit isn't set then we'll need to pad the
- // beginning with 0xff in order to keep the number negative.
- nMinus1 := new(big.Int).Neg(n)
- nMinus1.Sub(nMinus1, bigOne)
- bytes := nMinus1.Bytes()
- for i := range bytes {
- bytes[i] ^= 0xff
- }
- if len(bytes) == 0 || bytes[0]&0x80 == 0 {
- to[0] = 0xff
- to = to[1:]
- length++
- }
- nBytes := copy(to, bytes)
- to = to[nBytes:]
- length += nBytes
- } else if n.Sign() == 0 {
- // A zero is the zero length string
- } else {
- bytes := n.Bytes()
- if len(bytes) > 0 && bytes[0]&0x80 != 0 {
- // We'll have to pad this with a 0x00 in order to
- // stop it looking like a negative number.
- to[0] = 0
- to = to[1:]
- length++
- }
- nBytes := copy(to, bytes)
- to = to[nBytes:]
- length += nBytes
- }
-
- lengthBytes[0] = byte(length >> 24)
- lengthBytes[1] = byte(length >> 16)
- lengthBytes[2] = byte(length >> 8)
- lengthBytes[3] = byte(length)
- return to
-}
-
-func writeInt(w io.Writer, n *big.Int) {
- length := intLength(n)
- buf := make([]byte, length)
- marshalInt(buf, n)
- w.Write(buf)
-}
-
-func writeString(w io.Writer, s []byte) {
- var lengthBytes [4]byte
- lengthBytes[0] = byte(len(s) >> 24)
- lengthBytes[1] = byte(len(s) >> 16)
- lengthBytes[2] = byte(len(s) >> 8)
- lengthBytes[3] = byte(len(s))
- w.Write(lengthBytes[:])
- w.Write(s)
-}
-
-func stringLength(s []byte) int {
- return 4 + len(s)
-}
-
-func marshalString(to []byte, s []byte) []byte {
- to[0] = byte(len(s) >> 24)
- to[1] = byte(len(s) >> 16)
- to[2] = byte(len(s) >> 8)
- to[3] = byte(len(s))
- to = to[4:]
- copy(to, s)
- return to[len(s):]
-}
-
-var bigIntType = reflect.TypeOf((*big.Int)(nil))
-
-// Decode a packet into it's corresponding message.
-func decode(packet []byte) interface{} {
- var msg interface{}
- switch packet[0] {
- case msgDisconnect:
- msg = new(disconnectMsg)
- case msgServiceRequest:
- msg = new(serviceRequestMsg)
- case msgServiceAccept:
- msg = new(serviceAcceptMsg)
- case msgKexInit:
- msg = new(kexInitMsg)
- case msgKexDHInit:
- msg = new(kexDHInitMsg)
- case msgKexDHReply:
- msg = new(kexDHReplyMsg)
- case msgUserAuthRequest:
- msg = new(userAuthRequestMsg)
- case msgUserAuthFailure:
- msg = new(userAuthFailureMsg)
- case msgUserAuthPubKeyOk:
- msg = new(userAuthPubKeyOkMsg)
- case msgGlobalRequest:
- msg = new(globalRequestMsg)
- case msgRequestSuccess:
- msg = new(channelRequestSuccessMsg)
- case msgRequestFailure:
- msg = new(channelRequestFailureMsg)
- case msgChannelOpen:
- msg = new(channelOpenMsg)
- case msgChannelOpenConfirm:
- msg = new(channelOpenConfirmMsg)
- case msgChannelOpenFailure:
- msg = new(channelOpenFailureMsg)
- case msgChannelWindowAdjust:
- msg = new(windowAdjustMsg)
- case msgChannelEOF:
- msg = new(channelEOFMsg)
- case msgChannelClose:
- msg = new(channelCloseMsg)
- case msgChannelRequest:
- msg = new(channelRequestMsg)
- case msgChannelSuccess:
- msg = new(channelRequestSuccessMsg)
- case msgChannelFailure:
- msg = new(channelRequestFailureMsg)
- default:
- return UnexpectedMessageError{0, packet[0]}
- }
- if err := unmarshal(msg, packet, packet[0]); err != nil {
- return err
- }
- return msg
-}
diff --git a/libgo/go/exp/ssh/messages_test.go b/libgo/go/exp/ssh/messages_test.go
deleted file mode 100644
index fe4c397dc3a..00000000000
--- a/libgo/go/exp/ssh/messages_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "math/big"
- "math/rand"
- "reflect"
- "testing"
- "testing/quick"
-)
-
-var intLengthTests = []struct {
- val, length int
-}{
- {0, 4 + 0},
- {1, 4 + 1},
- {127, 4 + 1},
- {128, 4 + 2},
- {-1, 4 + 1},
-}
-
-func TestIntLength(t *testing.T) {
- for _, test := range intLengthTests {
- v := new(big.Int).SetInt64(int64(test.val))
- length := intLength(v)
- if length != test.length {
- t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
- }
- }
-}
-
-var messageTypes = []interface{}{
- &kexInitMsg{},
- &kexDHInitMsg{},
- &serviceRequestMsg{},
- &serviceAcceptMsg{},
- &userAuthRequestMsg{},
- &channelOpenMsg{},
- &channelOpenConfirmMsg{},
- &channelRequestMsg{},
- &channelRequestSuccessMsg{},
-}
-
-func TestMarshalUnmarshal(t *testing.T) {
- rand := rand.New(rand.NewSource(0))
- for i, iface := range messageTypes {
- ty := reflect.ValueOf(iface).Type()
-
- n := 100
- if testing.Short() {
- n = 5
- }
- for j := 0; j < n; j++ {
- v, ok := quick.Value(ty, rand)
- if !ok {
- t.Errorf("#%d: failed to create value", i)
- break
- }
-
- m1 := v.Elem().Interface()
- m2 := iface
-
- marshaled := marshal(msgIgnore, m1)
- if err := unmarshal(m2, marshaled, msgIgnore); err != nil {
- t.Errorf("#%d failed to unmarshal %#v: %s", i, m1, err)
- break
- }
-
- if !reflect.DeepEqual(v.Interface(), m2) {
- t.Errorf("#%d\ngot: %#v\nwant:%#v\n%x", i, m2, m1, marshaled)
- break
- }
- }
- }
-}
-
-func randomBytes(out []byte, rand *rand.Rand) {
- for i := 0; i < len(out); i++ {
- out[i] = byte(rand.Int31())
- }
-}
-
-func randomNameList(rand *rand.Rand) []string {
- ret := make([]string, rand.Int31()&15)
- for i := range ret {
- s := make([]byte, 1+(rand.Int31()&15))
- for j := range s {
- s[j] = 'a' + uint8(rand.Int31()&15)
- }
- ret[i] = string(s)
- }
- return ret
-}
-
-func randomInt(rand *rand.Rand) *big.Int {
- return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
-}
-
-func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
- ki := &kexInitMsg{}
- randomBytes(ki.Cookie[:], rand)
- ki.KexAlgos = randomNameList(rand)
- ki.ServerHostKeyAlgos = randomNameList(rand)
- ki.CiphersClientServer = randomNameList(rand)
- ki.CiphersServerClient = randomNameList(rand)
- ki.MACsClientServer = randomNameList(rand)
- ki.MACsServerClient = randomNameList(rand)
- ki.CompressionClientServer = randomNameList(rand)
- ki.CompressionServerClient = randomNameList(rand)
- ki.LanguagesClientServer = randomNameList(rand)
- ki.LanguagesServerClient = randomNameList(rand)
- if rand.Int31()&1 == 1 {
- ki.FirstKexFollows = true
- }
- return reflect.ValueOf(ki)
-}
-
-func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
- dhi := &kexDHInitMsg{}
- dhi.X = randomInt(rand)
- return reflect.ValueOf(dhi)
-}
diff --git a/libgo/go/exp/ssh/server.go b/libgo/go/exp/ssh/server.go
deleted file mode 100644
index 31011c66176..00000000000
--- a/libgo/go/exp/ssh/server.go
+++ /dev/null
@@ -1,676 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "bytes"
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "encoding/pem"
- "errors"
- "io"
- "math/big"
- "net"
- "sync"
-)
-
-type ServerConfig struct {
- rsa *rsa.PrivateKey
- rsaSerialized []byte
-
- // Rand provides the source of entropy for key exchange. If Rand is
- // nil, the cryptographic random reader in package crypto/rand will
- // be used.
- Rand io.Reader
-
- // NoClientAuth is true if clients are allowed to connect without
- // authenticating.
- NoClientAuth bool
-
- // PasswordCallback, if non-nil, is called when a user attempts to
- // authenticate using a password. It may be called concurrently from
- // several goroutines.
- PasswordCallback func(user, password string) bool
-
- // PublicKeyCallback, if non-nil, is called when a client attempts public
- // key authentication. It must return true iff the given public key is
- // valid for the given user.
- PublicKeyCallback func(user, algo string, pubkey []byte) bool
-
- // Cryptographic-related configuration.
- Crypto CryptoConfig
-}
-
-func (c *ServerConfig) rand() io.Reader {
- if c.Rand == nil {
- return rand.Reader
- }
- return c.Rand
-}
-
-// SetRSAPrivateKey sets the private key for a Server. A Server must have a
-// private key configured in order to accept connections. The private key must
-// be in the form of a PEM encoded, PKCS#1, RSA private key. The file "id_rsa"
-// typically contains such a key.
-func (s *ServerConfig) SetRSAPrivateKey(pemBytes []byte) error {
- block, _ := pem.Decode(pemBytes)
- if block == nil {
- return errors.New("ssh: no key found")
- }
- var err error
- s.rsa, err = x509.ParsePKCS1PrivateKey(block.Bytes)
- if err != nil {
- return err
- }
-
- s.rsaSerialized = marshalRSA(s.rsa)
- return nil
-}
-
-// marshalRSA serializes an RSA private key according to RFC 4256, section 6.6.
-func marshalRSA(priv *rsa.PrivateKey) []byte {
- e := new(big.Int).SetInt64(int64(priv.E))
- length := stringLength([]byte(hostAlgoRSA))
- length += intLength(e)
- length += intLength(priv.N)
-
- ret := make([]byte, length)
- r := marshalString(ret, []byte(hostAlgoRSA))
- r = marshalInt(r, e)
- r = marshalInt(r, priv.N)
-
- return ret
-}
-
-// parseRSA parses an RSA key according to RFC 4256, section 6.6.
-func parseRSA(in []byte) (pubKey *rsa.PublicKey, ok bool) {
- algo, in, ok := parseString(in)
- if !ok || string(algo) != hostAlgoRSA {
- return nil, false
- }
- bigE, in, ok := parseInt(in)
- if !ok || bigE.BitLen() > 24 {
- return nil, false
- }
- e := bigE.Int64()
- if e < 3 || e&1 == 0 {
- return nil, false
- }
- N, in, ok := parseInt(in)
- if !ok || len(in) > 0 {
- return nil, false
- }
- return &rsa.PublicKey{
- N: N,
- E: int(e),
- }, true
-}
-
-func parseRSASig(in []byte) (sig []byte, ok bool) {
- algo, in, ok := parseString(in)
- if !ok || string(algo) != hostAlgoRSA {
- return nil, false
- }
- sig, in, ok = parseString(in)
- if len(in) > 0 {
- ok = false
- }
- return
-}
-
-// cachedPubKey contains the results of querying whether a public key is
-// acceptable for a user. The cache only applies to a single ServerConn.
-type cachedPubKey struct {
- user, algo string
- pubKey []byte
- result bool
-}
-
-const maxCachedPubKeys = 16
-
-// A ServerConn represents an incomming connection.
-type ServerConn struct {
- *transport
- config *ServerConfig
-
- channels map[uint32]*channel
- nextChanId uint32
-
- // lock protects err and also allows Channels to serialise their writes
- // to out.
- lock sync.RWMutex
- err error
-
- // cachedPubKeys contains the cache results of tests for public keys.
- // Since SSH clients will query whether a public key is acceptable
- // before attempting to authenticate with it, we end up with duplicate
- // queries for public key validity.
- cachedPubKeys []cachedPubKey
-}
-
-// Server returns a new SSH server connection
-// using c as the underlying transport.
-func Server(c net.Conn, config *ServerConfig) *ServerConn {
- conn := &ServerConn{
- transport: newTransport(c, config.rand()),
- channels: make(map[uint32]*channel),
- config: config,
- }
- return conn
-}
-
-// kexDH performs Diffie-Hellman key agreement on a ServerConnection. The
-// returned values are given the same names as in RFC 4253, section 8.
-func (s *ServerConn) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) (H, K []byte, err error) {
- packet, err := s.readPacket()
- if err != nil {
- return
- }
- var kexDHInit kexDHInitMsg
- if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil {
- return
- }
-
- if kexDHInit.X.Sign() == 0 || kexDHInit.X.Cmp(group.p) >= 0 {
- return nil, nil, errors.New("client DH parameter out of bounds")
- }
-
- y, err := rand.Int(s.config.rand(), group.p)
- if err != nil {
- return
- }
-
- Y := new(big.Int).Exp(group.g, y, group.p)
- kInt := new(big.Int).Exp(kexDHInit.X, y, group.p)
-
- var serializedHostKey []byte
- switch hostKeyAlgo {
- case hostAlgoRSA:
- serializedHostKey = s.config.rsaSerialized
- default:
- return nil, nil, errors.New("internal error")
- }
-
- h := hashFunc.New()
- writeString(h, magics.clientVersion)
- writeString(h, magics.serverVersion)
- writeString(h, magics.clientKexInit)
- writeString(h, magics.serverKexInit)
- writeString(h, serializedHostKey)
- writeInt(h, kexDHInit.X)
- writeInt(h, Y)
- K = make([]byte, intLength(kInt))
- marshalInt(K, kInt)
- h.Write(K)
-
- H = h.Sum(nil)
-
- h.Reset()
- h.Write(H)
- hh := h.Sum(nil)
-
- var sig []byte
- switch hostKeyAlgo {
- case hostAlgoRSA:
- sig, err = rsa.SignPKCS1v15(s.config.rand(), s.config.rsa, hashFunc, hh)
- if err != nil {
- return
- }
- default:
- return nil, nil, errors.New("internal error")
- }
-
- serializedSig := serializeSignature(hostAlgoRSA, sig)
-
- kexDHReply := kexDHReplyMsg{
- HostKey: serializedHostKey,
- Y: Y,
- Signature: serializedSig,
- }
- packet = marshal(msgKexDHReply, kexDHReply)
-
- err = s.writePacket(packet)
- return
-}
-
-// serverVersion is the fixed identification string that Server will use.
-var serverVersion = []byte("SSH-2.0-Go\r\n")
-
-// Handshake performs an SSH transport and client authentication on the given ServerConn.
-func (s *ServerConn) Handshake() error {
- var magics handshakeMagics
- if _, err := s.Write(serverVersion); err != nil {
- return err
- }
- if err := s.Flush(); err != nil {
- return err
- }
- magics.serverVersion = serverVersion[:len(serverVersion)-2]
-
- version, err := readVersion(s)
- if err != nil {
- return err
- }
- magics.clientVersion = version
-
- serverKexInit := kexInitMsg{
- KexAlgos: supportedKexAlgos,
- ServerHostKeyAlgos: supportedHostKeyAlgos,
- CiphersClientServer: s.config.Crypto.ciphers(),
- CiphersServerClient: s.config.Crypto.ciphers(),
- MACsClientServer: supportedMACs,
- MACsServerClient: supportedMACs,
- CompressionClientServer: supportedCompressions,
- CompressionServerClient: supportedCompressions,
- }
- kexInitPacket := marshal(msgKexInit, serverKexInit)
- magics.serverKexInit = kexInitPacket
-
- if err := s.writePacket(kexInitPacket); err != nil {
- return err
- }
-
- packet, err := s.readPacket()
- if err != nil {
- return err
- }
-
- magics.clientKexInit = packet
-
- var clientKexInit kexInitMsg
- if err = unmarshal(&clientKexInit, packet, msgKexInit); err != nil {
- return err
- }
-
- kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, &clientKexInit, &serverKexInit)
- if !ok {
- return errors.New("ssh: no common algorithms")
- }
-
- if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0] {
- // The client sent a Kex message for the wrong algorithm,
- // which we have to ignore.
- if _, err := s.readPacket(); err != nil {
- return err
- }
- }
-
- var H, K []byte
- var hashFunc crypto.Hash
- switch kexAlgo {
- case kexAlgoDH14SHA1:
- hashFunc = crypto.SHA1
- dhGroup14Once.Do(initDHGroup14)
- H, K, err = s.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo)
- default:
- err = errors.New("ssh: unexpected key exchange algorithm " + kexAlgo)
- }
- if err != nil {
- return err
- }
-
- if err = s.writePacket([]byte{msgNewKeys}); err != nil {
- return err
- }
- if err = s.transport.writer.setupKeys(serverKeys, K, H, H, hashFunc); err != nil {
- return err
- }
- if packet, err = s.readPacket(); err != nil {
- return err
- }
-
- if packet[0] != msgNewKeys {
- return UnexpectedMessageError{msgNewKeys, packet[0]}
- }
- if err = s.transport.reader.setupKeys(clientKeys, K, H, H, hashFunc); err != nil {
- return err
- }
- if packet, err = s.readPacket(); err != nil {
- return err
- }
-
- var serviceRequest serviceRequestMsg
- if err = unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil {
- return err
- }
- if serviceRequest.Service != serviceUserAuth {
- return errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
- }
- serviceAccept := serviceAcceptMsg{
- Service: serviceUserAuth,
- }
- if err = s.writePacket(marshal(msgServiceAccept, serviceAccept)); err != nil {
- return err
- }
-
- if err = s.authenticate(H); err != nil {
- return err
- }
- return nil
-}
-
-func isAcceptableAlgo(algo string) bool {
- return algo == hostAlgoRSA
-}
-
-// testPubKey returns true if the given public key is acceptable for the user.
-func (s *ServerConn) testPubKey(user, algo string, pubKey []byte) bool {
- if s.config.PublicKeyCallback == nil || !isAcceptableAlgo(algo) {
- return false
- }
-
- for _, c := range s.cachedPubKeys {
- if c.user == user && c.algo == algo && bytes.Equal(c.pubKey, pubKey) {
- return c.result
- }
- }
-
- result := s.config.PublicKeyCallback(user, algo, pubKey)
- if len(s.cachedPubKeys) < maxCachedPubKeys {
- c := cachedPubKey{
- user: user,
- algo: algo,
- pubKey: make([]byte, len(pubKey)),
- result: result,
- }
- copy(c.pubKey, pubKey)
- s.cachedPubKeys = append(s.cachedPubKeys, c)
- }
-
- return result
-}
-
-func (s *ServerConn) authenticate(H []byte) error {
- var userAuthReq userAuthRequestMsg
- var err error
- var packet []byte
-
-userAuthLoop:
- for {
- if packet, err = s.readPacket(); err != nil {
- return err
- }
- if err = unmarshal(&userAuthReq, packet, msgUserAuthRequest); err != nil {
- return err
- }
-
- if userAuthReq.Service != serviceSSH {
- return errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
- }
-
- switch userAuthReq.Method {
- case "none":
- if s.config.NoClientAuth {
- break userAuthLoop
- }
- case "password":
- if s.config.PasswordCallback == nil {
- break
- }
- payload := userAuthReq.Payload
- if len(payload) < 1 || payload[0] != 0 {
- return ParseError{msgUserAuthRequest}
- }
- payload = payload[1:]
- password, payload, ok := parseString(payload)
- if !ok || len(payload) > 0 {
- return ParseError{msgUserAuthRequest}
- }
-
- if s.config.PasswordCallback(userAuthReq.User, string(password)) {
- break userAuthLoop
- }
- case "publickey":
- if s.config.PublicKeyCallback == nil {
- break
- }
- payload := userAuthReq.Payload
- if len(payload) < 1 {
- return ParseError{msgUserAuthRequest}
- }
- isQuery := payload[0] == 0
- payload = payload[1:]
- algoBytes, payload, ok := parseString(payload)
- if !ok {
- return ParseError{msgUserAuthRequest}
- }
- algo := string(algoBytes)
-
- pubKey, payload, ok := parseString(payload)
- if !ok {
- return ParseError{msgUserAuthRequest}
- }
- if isQuery {
- // The client can query if the given public key
- // would be ok.
- if len(payload) > 0 {
- return ParseError{msgUserAuthRequest}
- }
- if s.testPubKey(userAuthReq.User, algo, pubKey) {
- okMsg := userAuthPubKeyOkMsg{
- Algo: algo,
- PubKey: string(pubKey),
- }
- if err = s.writePacket(marshal(msgUserAuthPubKeyOk, okMsg)); err != nil {
- return err
- }
- continue userAuthLoop
- }
- } else {
- sig, payload, ok := parseString(payload)
- if !ok || len(payload) > 0 {
- return ParseError{msgUserAuthRequest}
- }
- if !isAcceptableAlgo(algo) {
- break
- }
- rsaSig, ok := parseRSASig(sig)
- if !ok {
- return ParseError{msgUserAuthRequest}
- }
- signedData := buildDataSignedForAuth(H, userAuthReq, algoBytes, pubKey)
- switch algo {
- case hostAlgoRSA:
- hashFunc := crypto.SHA1
- h := hashFunc.New()
- h.Write(signedData)
- digest := h.Sum(nil)
- rsaKey, ok := parseRSA(pubKey)
- if !ok {
- return ParseError{msgUserAuthRequest}
- }
- if rsa.VerifyPKCS1v15(rsaKey, hashFunc, digest, rsaSig) != nil {
- return ParseError{msgUserAuthRequest}
- }
- default:
- return errors.New("ssh: isAcceptableAlgo incorrect")
- }
- if s.testPubKey(userAuthReq.User, algo, pubKey) {
- break userAuthLoop
- }
- }
- }
-
- var failureMsg userAuthFailureMsg
- if s.config.PasswordCallback != nil {
- failureMsg.Methods = append(failureMsg.Methods, "password")
- }
- if s.config.PublicKeyCallback != nil {
- failureMsg.Methods = append(failureMsg.Methods, "publickey")
- }
-
- if len(failureMsg.Methods) == 0 {
- return errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
- }
-
- if err = s.writePacket(marshal(msgUserAuthFailure, failureMsg)); err != nil {
- return err
- }
- }
-
- packet = []byte{msgUserAuthSuccess}
- if err = s.writePacket(packet); err != nil {
- return err
- }
-
- return nil
-}
-
-const defaultWindowSize = 32768
-
-// Accept reads and processes messages on a ServerConn. It must be called
-// in order to demultiplex messages to any resulting Channels.
-func (s *ServerConn) Accept() (Channel, error) {
- if s.err != nil {
- return nil, s.err
- }
-
- for {
- packet, err := s.readPacket()
- if err != nil {
-
- s.lock.Lock()
- s.err = err
- s.lock.Unlock()
-
- for _, c := range s.channels {
- c.dead = true
- c.handleData(nil)
- }
-
- return nil, err
- }
-
- switch packet[0] {
- case msgChannelData:
- if len(packet) < 9 {
- // malformed data packet
- return nil, ParseError{msgChannelData}
- }
- peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
- s.lock.Lock()
- c, ok := s.channels[peersId]
- if !ok {
- s.lock.Unlock()
- continue
- }
- if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
- packet = packet[9:]
- c.handleData(packet[:length])
- }
- s.lock.Unlock()
- default:
- switch msg := decode(packet).(type) {
- case *channelOpenMsg:
- c := new(channel)
- c.chanType = msg.ChanType
- c.theirId = msg.PeersId
- c.theirWindow = msg.PeersWindow
- c.maxPacketSize = msg.MaxPacketSize
- c.extraData = msg.TypeSpecificData
- c.myWindow = defaultWindowSize
- c.serverConn = s
- c.cond = sync.NewCond(&c.lock)
- c.pendingData = make([]byte, c.myWindow)
-
- s.lock.Lock()
- c.myId = s.nextChanId
- s.nextChanId++
- s.channels[c.myId] = c
- s.lock.Unlock()
- return c, nil
-
- case *channelRequestMsg:
- s.lock.Lock()
- c, ok := s.channels[msg.PeersId]
- if !ok {
- s.lock.Unlock()
- continue
- }
- c.handlePacket(msg)
- s.lock.Unlock()
-
- case *channelEOFMsg:
- s.lock.Lock()
- c, ok := s.channels[msg.PeersId]
- if !ok {
- s.lock.Unlock()
- continue
- }
- c.handlePacket(msg)
- s.lock.Unlock()
-
- case *channelCloseMsg:
- s.lock.Lock()
- c, ok := s.channels[msg.PeersId]
- if !ok {
- s.lock.Unlock()
- continue
- }
- c.handlePacket(msg)
- s.lock.Unlock()
-
- case *globalRequestMsg:
- if msg.WantReply {
- if err := s.writePacket([]byte{msgRequestFailure}); err != nil {
- return nil, err
- }
- }
-
- case UnexpectedMessageError:
- return nil, msg
- case *disconnectMsg:
- return nil, io.EOF
- default:
- // Unknown message. Ignore.
- }
- }
- }
-
- panic("unreachable")
-}
-
-// A Listener implements a network listener (net.Listener) for SSH connections.
-type Listener struct {
- listener net.Listener
- config *ServerConfig
-}
-
-// Accept waits for and returns the next incoming SSH connection.
-// The receiver should call Handshake() in another goroutine
-// to avoid blocking the accepter.
-func (l *Listener) Accept() (*ServerConn, error) {
- c, err := l.listener.Accept()
- if err != nil {
- return nil, err
- }
- conn := Server(c, l.config)
- return conn, nil
-}
-
-// Addr returns the listener's network address.
-func (l *Listener) Addr() net.Addr {
- return l.listener.Addr()
-}
-
-// Close closes the listener.
-func (l *Listener) Close() error {
- return l.listener.Close()
-}
-
-// Listen creates an SSH listener accepting connections on
-// the given network address using net.Listen.
-func Listen(network, addr string, config *ServerConfig) (*Listener, error) {
- l, err := net.Listen(network, addr)
- if err != nil {
- return nil, err
- }
- return &Listener{
- l,
- config,
- }, nil
-}
diff --git a/libgo/go/exp/ssh/server_terminal.go b/libgo/go/exp/ssh/server_terminal.go
deleted file mode 100644
index 708a9159ec8..00000000000
--- a/libgo/go/exp/ssh/server_terminal.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-// A Terminal is capable of parsing and generating virtual terminal
-// data from an SSH client.
-type Terminal interface {
- ReadLine() (line string, err error)
- SetSize(x, y int)
- Write([]byte) (int, error)
-}
-
-// ServerTerminal contains the state for running a terminal that is capable of
-// reading lines of input.
-type ServerTerminal struct {
- Term Terminal
- Channel Channel
-}
-
-// parsePtyRequest parses the payload of the pty-req message and extracts the
-// dimensions of the terminal. See RFC 4254, section 6.2.
-func parsePtyRequest(s []byte) (width, height int, ok bool) {
- _, s, ok = parseString(s)
- if !ok {
- return
- }
- width32, s, ok := parseUint32(s)
- if !ok {
- return
- }
- height32, _, ok := parseUint32(s)
- width = int(width32)
- height = int(height32)
- if width < 1 {
- ok = false
- }
- if height < 1 {
- ok = false
- }
- return
-}
-
-func (ss *ServerTerminal) Write(buf []byte) (n int, err error) {
- return ss.Term.Write(buf)
-}
-
-// ReadLine returns a line of input from the terminal.
-func (ss *ServerTerminal) ReadLine() (line string, err error) {
- for {
- if line, err = ss.Term.ReadLine(); err == nil {
- return
- }
-
- req, ok := err.(ChannelRequest)
- if !ok {
- return
- }
-
- ok = false
- switch req.Request {
- case "pty-req":
- var width, height int
- width, height, ok = parsePtyRequest(req.Payload)
- ss.Term.SetSize(width, height)
- case "shell":
- ok = true
- if len(req.Payload) > 0 {
- // We don't accept any commands, only the default shell.
- ok = false
- }
- case "env":
- ok = true
- }
- if req.WantReply {
- ss.Channel.AckRequest(ok)
- }
- }
- panic("unreachable")
-}
diff --git a/libgo/go/exp/ssh/session.go b/libgo/go/exp/ssh/session.go
deleted file mode 100644
index ea4addbd50b..00000000000
--- a/libgo/go/exp/ssh/session.go
+++ /dev/null
@@ -1,494 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-// Session implements an interactive session described in
-// "RFC 4254, section 6".
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
-)
-
-type Signal string
-
-// POSIX signals as listed in RFC 4254 Section 6.10.
-const (
- SIGABRT Signal = "ABRT"
- SIGALRM Signal = "ALRM"
- SIGFPE Signal = "FPE"
- SIGHUP Signal = "HUP"
- SIGILL Signal = "ILL"
- SIGINT Signal = "INT"
- SIGKILL Signal = "KILL"
- SIGPIPE Signal = "PIPE"
- SIGQUIT Signal = "QUIT"
- SIGSEGV Signal = "SEGV"
- SIGTERM Signal = "TERM"
- SIGUSR1 Signal = "USR1"
- SIGUSR2 Signal = "USR2"
-)
-
-var signals = map[Signal]int{
- SIGABRT: 6,
- SIGALRM: 14,
- SIGFPE: 8,
- SIGHUP: 1,
- SIGILL: 4,
- SIGINT: 2,
- SIGKILL: 9,
- SIGPIPE: 13,
- SIGQUIT: 3,
- SIGSEGV: 11,
- SIGTERM: 15,
-}
-
-// A Session represents a connection to a remote command or shell.
-type Session struct {
- // Stdin specifies the remote process's standard input.
- // If Stdin is nil, the remote process reads from an empty
- // bytes.Buffer.
- Stdin io.Reader
-
- // Stdout and Stderr specify the remote process's standard
- // output and error.
- //
- // If either is nil, Run connects the corresponding file
- // descriptor to an instance of ioutil.Discard. There is a
- // fixed amount of buffering that is shared for the two streams.
- // If either blocks it may eventually cause the remote
- // command to block.
- Stdout io.Writer
- Stderr io.Writer
-
- *clientChan // the channel backing this session
-
- started bool // true once Start, Run or Shell is invoked.
- copyFuncs []func() error
- errors chan error // one send per copyFunc
-
- // true if pipe method is active
- stdinpipe, stdoutpipe, stderrpipe bool
-}
-
-// RFC 4254 Section 6.4.
-type setenvRequest struct {
- PeersId uint32
- Request string
- WantReply bool
- Name string
- Value string
-}
-
-// Setenv sets an environment variable that will be applied to any
-// command executed by Shell or Run.
-func (s *Session) Setenv(name, value string) error {
- req := setenvRequest{
- PeersId: s.peersId,
- Request: "env",
- WantReply: true,
- Name: name,
- Value: value,
- }
- if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
- return err
- }
- return s.waitForResponse()
-}
-
-// An empty mode list, see RFC 4254 Section 8.
-var emptyModelist = "\x00"
-
-// RFC 4254 Section 6.2.
-type ptyRequestMsg struct {
- PeersId uint32
- Request string
- WantReply bool
- Term string
- Columns uint32
- Rows uint32
- Width uint32
- Height uint32
- Modelist string
-}
-
-// RequestPty requests the association of a pty with the session on the remote host.
-func (s *Session) RequestPty(term string, h, w int) error {
- req := ptyRequestMsg{
- PeersId: s.peersId,
- Request: "pty-req",
- WantReply: true,
- Term: term,
- Columns: uint32(w),
- Rows: uint32(h),
- Width: uint32(w * 8),
- Height: uint32(h * 8),
- Modelist: emptyModelist,
- }
- if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
- return err
- }
- return s.waitForResponse()
-}
-
-// RFC 4254 Section 6.9.
-type signalMsg struct {
- PeersId uint32
- Request string
- WantReply bool
- Signal string
-}
-
-// Signal sends the given signal to the remote process.
-// sig is one of the SIG* constants.
-func (s *Session) Signal(sig Signal) error {
- req := signalMsg{
- PeersId: s.peersId,
- Request: "signal",
- WantReply: false,
- Signal: string(sig),
- }
- return s.writePacket(marshal(msgChannelRequest, req))
-}
-
-// RFC 4254 Section 6.5.
-type execMsg struct {
- PeersId uint32
- Request string
- WantReply bool
- Command string
-}
-
-// Start runs cmd on the remote host. Typically, the remote
-// server passes cmd to the shell for interpretation.
-// A Session only accepts one call to Run, Start or Shell.
-func (s *Session) Start(cmd string) error {
- if s.started {
- return errors.New("ssh: session already started")
- }
- req := execMsg{
- PeersId: s.peersId,
- Request: "exec",
- WantReply: true,
- Command: cmd,
- }
- if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
- return err
- }
- if err := s.waitForResponse(); err != nil {
- return fmt.Errorf("ssh: could not execute command %s: %v", cmd, err)
- }
- return s.start()
-}
-
-// Run runs cmd on the remote host. Typically, the remote
-// server passes cmd to the shell for interpretation.
-// A Session only accepts one call to Run, Start or Shell.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *ExitError. Other error types may be
-// returned for I/O problems.
-func (s *Session) Run(cmd string) error {
- err := s.Start(cmd)
- if err != nil {
- return err
- }
- return s.Wait()
-}
-
-// Shell starts a login shell on the remote host. A Session only
-// accepts one call to Run, Start or Shell.
-func (s *Session) Shell() error {
- if s.started {
- return errors.New("ssh: session already started")
- }
- req := channelRequestMsg{
- PeersId: s.peersId,
- Request: "shell",
- WantReply: true,
- }
- if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
- return err
- }
- if err := s.waitForResponse(); err != nil {
- return fmt.Errorf("ssh: cound not execute shell: %v", err)
- }
- return s.start()
-}
-
-func (s *Session) waitForResponse() error {
- msg := <-s.msg
- switch msg.(type) {
- case *channelRequestSuccessMsg:
- return nil
- case *channelRequestFailureMsg:
- return errors.New("request failed")
- }
- return fmt.Errorf("unknown packet %T received: %v", msg, msg)
-}
-
-func (s *Session) start() error {
- s.started = true
-
- type F func(*Session)
- for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} {
- setupFd(s)
- }
-
- s.errors = make(chan error, len(s.copyFuncs))
- for _, fn := range s.copyFuncs {
- go func(fn func() error) {
- s.errors <- fn()
- }(fn)
- }
- return nil
-}
-
-// Wait waits for the remote command to exit.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *ExitError. Other error types may be
-// returned for I/O problems.
-func (s *Session) Wait() error {
- if !s.started {
- return errors.New("ssh: session not started")
- }
- waitErr := s.wait()
-
- var copyError error
- for _ = range s.copyFuncs {
- if err := <-s.errors; err != nil && copyError == nil {
- copyError = err
- }
- }
- if waitErr != nil {
- return waitErr
- }
- return copyError
-}
-
-func (s *Session) wait() error {
- wm := Waitmsg{status: -1}
-
- // Wait for msg channel to be closed before returning.
- for msg := range s.msg {
- switch msg := msg.(type) {
- case *channelRequestMsg:
- switch msg.Request {
- case "exit-status":
- d := msg.RequestSpecificData
- wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3])
- case "exit-signal":
- signal, rest, ok := parseString(msg.RequestSpecificData)
- if !ok {
- return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
- }
- wm.signal = safeString(string(signal))
-
- // skip coreDumped bool
- if len(rest) == 0 {
- return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
- }
- rest = rest[1:]
-
- errmsg, rest, ok := parseString(rest)
- if !ok {
- return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
- }
- wm.msg = safeString(string(errmsg))
-
- lang, _, ok := parseString(rest)
- if !ok {
- return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
- }
- wm.lang = safeString(string(lang))
- default:
- return fmt.Errorf("wait: unexpected channel request: %v", msg)
- }
- default:
- return fmt.Errorf("wait: unexpected packet %T received: %v", msg, msg)
- }
- }
- if wm.status == 0 {
- return nil
- }
- if wm.status == -1 {
- // exit-status was never sent from server
- if wm.signal == "" {
- return errors.New("wait: remote command exited without exit status or exit signal")
- }
- wm.status = 128
- if _, ok := signals[Signal(wm.signal)]; ok {
- wm.status += signals[Signal(wm.signal)]
- }
- }
- return &ExitError{wm}
-}
-
-func (s *Session) stdin() {
- if s.stdinpipe {
- return
- }
- if s.Stdin == nil {
- s.Stdin = new(bytes.Buffer)
- }
- s.copyFuncs = append(s.copyFuncs, func() error {
- _, err := io.Copy(s.clientChan.stdin, s.Stdin)
- if err1 := s.clientChan.stdin.Close(); err == nil {
- err = err1
- }
- return err
- })
-}
-
-func (s *Session) stdout() {
- if s.stdoutpipe {
- return
- }
- if s.Stdout == nil {
- s.Stdout = ioutil.Discard
- }
- s.copyFuncs = append(s.copyFuncs, func() error {
- _, err := io.Copy(s.Stdout, s.clientChan.stdout)
- return err
- })
-}
-
-func (s *Session) stderr() {
- if s.stderrpipe {
- return
- }
- if s.Stderr == nil {
- s.Stderr = ioutil.Discard
- }
- s.copyFuncs = append(s.copyFuncs, func() error {
- _, err := io.Copy(s.Stderr, s.clientChan.stderr)
- return err
- })
-}
-
-// StdinPipe returns a pipe that will be connected to the
-// remote command's standard input when the command starts.
-func (s *Session) StdinPipe() (io.WriteCloser, error) {
- if s.Stdin != nil {
- return nil, errors.New("ssh: Stdin already set")
- }
- if s.started {
- return nil, errors.New("ssh: StdinPipe after process started")
- }
- s.stdinpipe = true
- return s.clientChan.stdin, nil
-}
-
-// StdoutPipe returns a pipe that will be connected to the
-// remote command's standard output when the command starts.
-// There is a fixed amount of buffering that is shared between
-// stdout and stderr streams. If the StdoutPipe reader is
-// not serviced fast enought it may eventually cause the
-// remote command to block.
-func (s *Session) StdoutPipe() (io.Reader, error) {
- if s.Stdout != nil {
- return nil, errors.New("ssh: Stdout already set")
- }
- if s.started {
- return nil, errors.New("ssh: StdoutPipe after process started")
- }
- s.stdoutpipe = true
- return s.clientChan.stdout, nil
-}
-
-// StderrPipe returns a pipe that will be connected to the
-// remote command's standard error when the command starts.
-// There is a fixed amount of buffering that is shared between
-// stdout and stderr streams. If the StderrPipe reader is
-// not serviced fast enought it may eventually cause the
-// remote command to block.
-func (s *Session) StderrPipe() (io.Reader, error) {
- if s.Stderr != nil {
- return nil, errors.New("ssh: Stderr already set")
- }
- if s.started {
- return nil, errors.New("ssh: StderrPipe after process started")
- }
- s.stderrpipe = true
- return s.clientChan.stderr, nil
-}
-
-// TODO(dfc) add Output and CombinedOutput helpers
-
-// NewSession returns a new interactive session on the remote host.
-func (c *ClientConn) NewSession() (*Session, error) {
- ch := c.newChan(c.transport)
- if err := c.writePacket(marshal(msgChannelOpen, channelOpenMsg{
- ChanType: "session",
- PeersId: ch.id,
- PeersWindow: 1 << 14,
- MaxPacketSize: 1 << 15, // RFC 4253 6.1
- })); err != nil {
- c.chanlist.remove(ch.id)
- return nil, err
- }
- if err := ch.waitForChannelOpenResponse(); err != nil {
- c.chanlist.remove(ch.id)
- return nil, fmt.Errorf("ssh: unable to open session: %v", err)
- }
- return &Session{
- clientChan: ch,
- }, nil
-}
-
-// An ExitError reports unsuccessful completion of a remote command.
-type ExitError struct {
- Waitmsg
-}
-
-func (e *ExitError) Error() string {
- return e.Waitmsg.String()
-}
-
-// Waitmsg stores the information about an exited remote command
-// as reported by Wait.
-type Waitmsg struct {
- status int
- signal string
- msg string
- lang string
-}
-
-// ExitStatus returns the exit status of the remote command.
-func (w Waitmsg) ExitStatus() int {
- return w.status
-}
-
-// Signal returns the exit signal of the remote command if
-// it was terminated violently.
-func (w Waitmsg) Signal() string {
- return w.signal
-}
-
-// Msg returns the exit message given by the remote command
-func (w Waitmsg) Msg() string {
- return w.msg
-}
-
-// Lang returns the language tag. See RFC 3066
-func (w Waitmsg) Lang() string {
- return w.lang
-}
-
-func (w Waitmsg) String() string {
- return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.status, w.msg, w.signal)
-}
diff --git a/libgo/go/exp/ssh/session_test.go b/libgo/go/exp/ssh/session_test.go
deleted file mode 100644
index 4a3d22bee04..00000000000
--- a/libgo/go/exp/ssh/session_test.go
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-// Session tests.
-
-import (
- "bytes"
- "exp/terminal"
- "io"
- "testing"
-)
-
-type serverType func(*channel)
-
-// dial constructs a new test server and returns a *ClientConn.
-func dial(handler serverType, t *testing.T) *ClientConn {
- pw := password("tiger")
- serverConfig.PasswordCallback = func(user, pass string) bool {
- return user == "testuser" && pass == string(pw)
- }
- serverConfig.PublicKeyCallback = nil
-
- l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
- if err != nil {
- t.Fatalf("unable to listen: %s", err)
- }
- go func() {
- defer l.Close()
- conn, err := l.Accept()
- if err != nil {
- t.Errorf("Unable to accept: %v", err)
- return
- }
- defer conn.Close()
- if err := conn.Handshake(); err != nil {
- t.Errorf("Unable to handshake: %v", err)
- return
- }
- for {
- ch, err := conn.Accept()
- if err == io.EOF {
- return
- }
- if err != nil {
- t.Errorf("Unable to accept incoming channel request: %v", err)
- return
- }
- if ch.ChannelType() != "session" {
- ch.Reject(UnknownChannelType, "unknown channel type")
- continue
- }
- ch.Accept()
- go handler(ch.(*channel))
- }
- t.Log("done")
- }()
-
- config := &ClientConfig{
- User: "testuser",
- Auth: []ClientAuth{
- ClientAuthPassword(pw),
- },
- }
-
- c, err := Dial("tcp", l.Addr().String(), config)
- if err != nil {
- t.Fatalf("unable to dial remote side: %s", err)
- }
- return c
-}
-
-// Test a simple string is returned to session.Stdout.
-func TestSessionShell(t *testing.T) {
- conn := dial(shellHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- stdout := new(bytes.Buffer)
- session.Stdout = stdout
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- if err := session.Wait(); err != nil {
- t.Fatalf("Remote command did not exit cleanly: %s", err)
- }
- actual := stdout.String()
- if actual != "golang" {
- t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
- }
-}
-
-// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
-
-// Test a simple string is returned via StdoutPipe.
-func TestSessionStdoutPipe(t *testing.T) {
- conn := dial(shellHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- stdout, err := session.StdoutPipe()
- if err != nil {
- t.Fatalf("Unable to request StdoutPipe(): %v", err)
- }
- var buf bytes.Buffer
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- done := make(chan bool, 1)
- go func() {
- if _, err := io.Copy(&buf, stdout); err != nil {
- t.Errorf("Copy of stdout failed: %v", err)
- }
- done <- true
- }()
- if err := session.Wait(); err != nil {
- t.Fatalf("Remote command did not exit cleanly: %s", err)
- }
- <-done
- actual := buf.String()
- if actual != "golang" {
- t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
- }
-}
-
-// Test non-0 exit status is returned correctly.
-func TestExitStatusNonZero(t *testing.T) {
- conn := dial(exitStatusNonZeroHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- err = session.Wait()
- if err == nil {
- t.Fatalf("expected command to fail but it didn't")
- }
- e, ok := err.(*ExitError)
- if !ok {
- t.Fatalf("expected *ExitError but got %T", err)
- }
- if e.ExitStatus() != 15 {
- t.Fatalf("expected command to exit with 15 but got %s", e.ExitStatus())
- }
-}
-
-// Test 0 exit status is returned correctly.
-func TestExitStatusZero(t *testing.T) {
- conn := dial(exitStatusZeroHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
-
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- err = session.Wait()
- if err != nil {
- t.Fatalf("expected nil but got %s", err)
- }
-}
-
-// Test exit signal and status are both returned correctly.
-func TestExitSignalAndStatus(t *testing.T) {
- conn := dial(exitSignalAndStatusHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- err = session.Wait()
- if err == nil {
- t.Fatalf("expected command to fail but it didn't")
- }
- e, ok := err.(*ExitError)
- if !ok {
- t.Fatalf("expected *ExitError but got %T", err)
- }
- if e.Signal() != "TERM" || e.ExitStatus() != 15 {
- t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
- }
-}
-
-// Test exit signal and status are both returned correctly.
-func TestKnownExitSignalOnly(t *testing.T) {
- conn := dial(exitSignalHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- err = session.Wait()
- if err == nil {
- t.Fatalf("expected command to fail but it didn't")
- }
- e, ok := err.(*ExitError)
- if !ok {
- t.Fatalf("expected *ExitError but got %T", err)
- }
- if e.Signal() != "TERM" || e.ExitStatus() != 143 {
- t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
- }
-}
-
-// Test exit signal and status are both returned correctly.
-func TestUnknownExitSignal(t *testing.T) {
- conn := dial(exitSignalUnknownHandler, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- err = session.Wait()
- if err == nil {
- t.Fatalf("expected command to fail but it didn't")
- }
- e, ok := err.(*ExitError)
- if !ok {
- t.Fatalf("expected *ExitError but got %T", err)
- }
- if e.Signal() != "SYS" || e.ExitStatus() != 128 {
- t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
- }
-}
-
-// Test WaitMsg is not returned if the channel closes abruptly.
-func TestExitWithoutStatusOrSignal(t *testing.T) {
- conn := dial(exitWithoutSignalOrStatus, t)
- defer conn.Close()
- session, err := conn.NewSession()
- if err != nil {
- t.Fatalf("Unable to request new session: %s", err)
- }
- defer session.Close()
- if err := session.Shell(); err != nil {
- t.Fatalf("Unable to execute command: %s", err)
- }
- err = session.Wait()
- if err == nil {
- t.Fatalf("expected command to fail but it didn't")
- }
- _, ok := err.(*ExitError)
- if ok {
- // you can't actually test for errors.errorString
- // because it's not exported.
- t.Fatalf("expected *errorString but got %T", err)
- }
-}
-
-type exitStatusMsg struct {
- PeersId uint32
- Request string
- WantReply bool
- Status uint32
-}
-
-type exitSignalMsg struct {
- PeersId uint32
- Request string
- WantReply bool
- Signal string
- CoreDumped bool
- Errmsg string
- Lang string
-}
-
-func newServerShell(ch *channel, prompt string) *ServerTerminal {
- term := terminal.NewTerminal(ch, prompt)
- return &ServerTerminal{
- Term: term,
- Channel: ch,
- }
-}
-
-func exitStatusZeroHandler(ch *channel) {
- defer ch.Close()
- // this string is returned to stdout
- shell := newServerShell(ch, "> ")
- shell.ReadLine()
- sendStatus(0, ch)
-}
-
-func exitStatusNonZeroHandler(ch *channel) {
- defer ch.Close()
- shell := newServerShell(ch, "> ")
- shell.ReadLine()
- sendStatus(15, ch)
-}
-
-func exitSignalAndStatusHandler(ch *channel) {
- defer ch.Close()
- shell := newServerShell(ch, "> ")
- shell.ReadLine()
- sendStatus(15, ch)
- sendSignal("TERM", ch)
-}
-
-func exitSignalHandler(ch *channel) {
- defer ch.Close()
- shell := newServerShell(ch, "> ")
- shell.ReadLine()
- sendSignal("TERM", ch)
-}
-
-func exitSignalUnknownHandler(ch *channel) {
- defer ch.Close()
- shell := newServerShell(ch, "> ")
- shell.ReadLine()
- sendSignal("SYS", ch)
-}
-
-func exitWithoutSignalOrStatus(ch *channel) {
- defer ch.Close()
- shell := newServerShell(ch, "> ")
- shell.ReadLine()
-}
-
-func shellHandler(ch *channel) {
- defer ch.Close()
- // this string is returned to stdout
- shell := newServerShell(ch, "golang")
- shell.ReadLine()
- sendStatus(0, ch)
-}
-
-func sendStatus(status uint32, ch *channel) {
- msg := exitStatusMsg{
- PeersId: ch.theirId,
- Request: "exit-status",
- WantReply: false,
- Status: status,
- }
- ch.serverConn.writePacket(marshal(msgChannelRequest, msg))
-}
-
-func sendSignal(signal string, ch *channel) {
- sig := exitSignalMsg{
- PeersId: ch.theirId,
- Request: "exit-signal",
- WantReply: false,
- Signal: signal,
- CoreDumped: false,
- Errmsg: "Process terminated",
- Lang: "en-GB-oed",
- }
- ch.serverConn.writePacket(marshal(msgChannelRequest, sig))
-}
diff --git a/libgo/go/exp/ssh/tcpip.go b/libgo/go/exp/ssh/tcpip.go
deleted file mode 100644
index e0c47bca1fc..00000000000
--- a/libgo/go/exp/ssh/tcpip.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "errors"
- "fmt"
- "io"
- "net"
- "time"
-)
-
-// Dial initiates a connection to the addr from the remote host.
-// addr is resolved using net.ResolveTCPAddr before connection.
-// This could allow an observer to observe the DNS name of the
-// remote host. Consider using ssh.DialTCP to avoid this.
-func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
- raddr, err := net.ResolveTCPAddr(n, addr)
- if err != nil {
- return nil, err
- }
- return c.DialTCP(n, nil, raddr)
-}
-
-// DialTCP connects to the remote address raddr on the network net,
-// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
-// as the local address for the connection.
-func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
- if laddr == nil {
- laddr = &net.TCPAddr{
- IP: net.IPv4zero,
- Port: 0,
- }
- }
- ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
- if err != nil {
- return nil, err
- }
- return &tcpchanconn{
- tcpchan: ch,
- laddr: laddr,
- raddr: raddr,
- }, nil
-}
-
-// RFC 4254 7.2
-type channelOpenDirectMsg struct {
- ChanType string
- PeersId uint32
- PeersWindow uint32
- MaxPacketSize uint32
- raddr string
- rport uint32
- laddr string
- lport uint32
-}
-
-// dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
-// strings and are expected to be resolveable at the remote end.
-func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) {
- ch := c.newChan(c.transport)
- if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
- ChanType: "direct-tcpip",
- PeersId: ch.id,
- PeersWindow: 1 << 14,
- MaxPacketSize: 1 << 15, // RFC 4253 6.1
- raddr: raddr,
- rport: uint32(rport),
- laddr: laddr,
- lport: uint32(lport),
- })); err != nil {
- c.chanlist.remove(ch.id)
- return nil, err
- }
- if err := ch.waitForChannelOpenResponse(); err != nil {
- c.chanlist.remove(ch.id)
- return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
- }
- return &tcpchan{
- clientChan: ch,
- Reader: ch.stdout,
- Writer: ch.stdin,
- }, nil
-}
-
-type tcpchan struct {
- *clientChan // the backing channel
- io.Reader
- io.Writer
-}
-
-// tcpchanconn fulfills the net.Conn interface without
-// the tcpchan having to hold laddr or raddr directly.
-type tcpchanconn struct {
- *tcpchan
- laddr, raddr net.Addr
-}
-
-// LocalAddr returns the local network address.
-func (t *tcpchanconn) LocalAddr() net.Addr {
- return t.laddr
-}
-
-// RemoteAddr returns the remote network address.
-func (t *tcpchanconn) RemoteAddr() net.Addr {
- return t.raddr
-}
-
-// SetDeadline sets the read and write deadlines associated
-// with the connection.
-func (t *tcpchanconn) SetDeadline(deadline time.Time) error {
- if err := t.SetReadDeadline(deadline); err != nil {
- return err
- }
- return t.SetWriteDeadline(deadline)
-}
-
-// SetReadDeadline sets the read deadline.
-// A zero value for t means Read will not time out.
-// After the deadline, the error from Read will implement net.Error
-// with Timeout() == true.
-func (t *tcpchanconn) SetReadDeadline(deadline time.Time) error {
- return errors.New("ssh: tcpchan: deadline not supported")
-}
-
-// SetWriteDeadline exists to satisfy the net.Conn interface
-// but is not implemented by this type. It always returns an error.
-func (t *tcpchanconn) SetWriteDeadline(deadline time.Time) error {
- return errors.New("ssh: tcpchan: deadline not supported")
-}
diff --git a/libgo/go/exp/ssh/tcpip_func_test.go b/libgo/go/exp/ssh/tcpip_func_test.go
deleted file mode 100644
index 261297241e9..00000000000
--- a/libgo/go/exp/ssh/tcpip_func_test.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-// direct-tcpip functional tests
-
-import (
- "net"
- "net/http"
- "testing"
-)
-
-func TestTCPIPHTTP(t *testing.T) {
- if *sshuser == "" {
- t.Log("ssh.user not defined, skipping test")
- return
- }
- // google.com will generate at least one redirect, possibly three
- // depending on your location.
- doTest(t, "http://google.com")
-}
-
-func TestTCPIPHTTPS(t *testing.T) {
- if *sshuser == "" {
- t.Log("ssh.user not defined, skipping test")
- return
- }
- doTest(t, "https://encrypted.google.com/")
-}
-
-func doTest(t *testing.T, url string) {
- config := &ClientConfig{
- User: *sshuser,
- Auth: []ClientAuth{
- ClientAuthPassword(password(*sshpass)),
- },
- }
- conn, err := Dial("tcp", "localhost:22", config)
- if err != nil {
- t.Fatalf("Unable to connect: %s", err)
- }
- defer conn.Close()
- tr := &http.Transport{
- Dial: func(n, addr string) (net.Conn, error) {
- return conn.Dial(n, addr)
- },
- }
- client := &http.Client{
- Transport: tr,
- }
- resp, err := client.Get(url)
- if err != nil {
- t.Fatalf("unable to proxy: %s", err)
- }
- // got a body without error
- t.Log(resp)
-}
diff --git a/libgo/go/exp/ssh/transport.go b/libgo/go/exp/ssh/transport.go
deleted file mode 100644
index e21bc4ba202..00000000000
--- a/libgo/go/exp/ssh/transport.go
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "bufio"
- "crypto"
- "crypto/cipher"
- "crypto/hmac"
- "crypto/sha1"
- "crypto/subtle"
- "errors"
- "hash"
- "io"
- "net"
- "sync"
-)
-
-const (
- packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
- minPacketSize = 16
- maxPacketSize = 36000
- minPaddingSize = 4 // TODO(huin) should this be configurable?
-)
-
-// filteredConn reduces the set of methods exposed when embeddeding
-// a net.Conn inside ssh.transport.
-// TODO(dfc) suggestions for a better name will be warmly received.
-type filteredConn interface {
- // Close closes the connection.
- Close() error
-
- // LocalAddr returns the local network address.
- LocalAddr() net.Addr
-
- // RemoteAddr returns the remote network address.
- RemoteAddr() net.Addr
-}
-
-// Types implementing packetWriter provide the ability to send packets to
-// an SSH peer.
-type packetWriter interface {
- // Encrypt and send a packet of data to the remote peer.
- writePacket(packet []byte) error
-}
-
-// transport represents the SSH connection to the remote peer.
-type transport struct {
- reader
- writer
-
- filteredConn
-}
-
-// reader represents the incoming connection state.
-type reader struct {
- io.Reader
- common
-}
-
-// writer represnts the outgoing connection state.
-type writer struct {
- *sync.Mutex // protects writer.Writer from concurrent writes
- *bufio.Writer
- rand io.Reader
- common
-}
-
-// common represents the cipher state needed to process messages in a single
-// direction.
-type common struct {
- seqNum uint32
- mac hash.Hash
- cipher cipher.Stream
-
- cipherAlgo string
- macAlgo string
- compressionAlgo string
-}
-
-// Read and decrypt a single packet from the remote peer.
-func (r *reader) readOnePacket() ([]byte, error) {
- var lengthBytes = make([]byte, 5)
- var macSize uint32
- if _, err := io.ReadFull(r, lengthBytes); err != nil {
- return nil, err
- }
-
- r.cipher.XORKeyStream(lengthBytes, lengthBytes)
-
- if r.mac != nil {
- r.mac.Reset()
- seqNumBytes := []byte{
- byte(r.seqNum >> 24),
- byte(r.seqNum >> 16),
- byte(r.seqNum >> 8),
- byte(r.seqNum),
- }
- r.mac.Write(seqNumBytes)
- r.mac.Write(lengthBytes)
- macSize = uint32(r.mac.Size())
- }
-
- length := uint32(lengthBytes[0])<<24 | uint32(lengthBytes[1])<<16 | uint32(lengthBytes[2])<<8 | uint32(lengthBytes[3])
- paddingLength := uint32(lengthBytes[4])
-
- if length <= paddingLength+1 {
- return nil, errors.New("invalid packet length")
- }
- if length > maxPacketSize {
- return nil, errors.New("packet too large")
- }
-
- packet := make([]byte, length-1+macSize)
- if _, err := io.ReadFull(r, packet); err != nil {
- return nil, err
- }
- mac := packet[length-1:]
- r.cipher.XORKeyStream(packet, packet[:length-1])
-
- if r.mac != nil {
- r.mac.Write(packet[:length-1])
- if subtle.ConstantTimeCompare(r.mac.Sum(nil), mac) != 1 {
- return nil, errors.New("ssh: MAC failure")
- }
- }
-
- r.seqNum++
- return packet[:length-paddingLength-1], nil
-}
-
-// Read and decrypt next packet discarding debug and noop messages.
-func (t *transport) readPacket() ([]byte, error) {
- for {
- packet, err := t.readOnePacket()
- if err != nil {
- return nil, err
- }
- if packet[0] != msgIgnore && packet[0] != msgDebug {
- return packet, nil
- }
- }
- panic("unreachable")
-}
-
-// Encrypt and send a packet of data to the remote peer.
-func (w *writer) writePacket(packet []byte) error {
- w.Mutex.Lock()
- defer w.Mutex.Unlock()
-
- paddingLength := packetSizeMultiple - (5+len(packet))%packetSizeMultiple
- if paddingLength < 4 {
- paddingLength += packetSizeMultiple
- }
-
- length := len(packet) + 1 + paddingLength
- lengthBytes := []byte{
- byte(length >> 24),
- byte(length >> 16),
- byte(length >> 8),
- byte(length),
- byte(paddingLength),
- }
- padding := make([]byte, paddingLength)
- _, err := io.ReadFull(w.rand, padding)
- if err != nil {
- return err
- }
-
- if w.mac != nil {
- w.mac.Reset()
- seqNumBytes := []byte{
- byte(w.seqNum >> 24),
- byte(w.seqNum >> 16),
- byte(w.seqNum >> 8),
- byte(w.seqNum),
- }
- w.mac.Write(seqNumBytes)
- w.mac.Write(lengthBytes)
- w.mac.Write(packet)
- w.mac.Write(padding)
- }
-
- // TODO(dfc) lengthBytes, packet and padding should be
- // subslices of a single buffer
- w.cipher.XORKeyStream(lengthBytes, lengthBytes)
- w.cipher.XORKeyStream(packet, packet)
- w.cipher.XORKeyStream(padding, padding)
-
- if _, err := w.Write(lengthBytes); err != nil {
- return err
- }
- if _, err := w.Write(packet); err != nil {
- return err
- }
- if _, err := w.Write(padding); err != nil {
- return err
- }
-
- if w.mac != nil {
- if _, err := w.Write(w.mac.Sum(nil)); err != nil {
- return err
- }
- }
-
- if err := w.Flush(); err != nil {
- return err
- }
- w.seqNum++
- return err
-}
-
-// Send a message to the remote peer
-func (t *transport) sendMessage(typ uint8, msg interface{}) error {
- packet := marshal(typ, msg)
- return t.writePacket(packet)
-}
-
-func newTransport(conn net.Conn, rand io.Reader) *transport {
- return &transport{
- reader: reader{
- Reader: bufio.NewReader(conn),
- common: common{
- cipher: noneCipher{},
- },
- },
- writer: writer{
- Writer: bufio.NewWriter(conn),
- rand: rand,
- Mutex: new(sync.Mutex),
- common: common{
- cipher: noneCipher{},
- },
- },
- filteredConn: conn,
- }
-}
-
-type direction struct {
- ivTag []byte
- keyTag []byte
- macKeyTag []byte
-}
-
-// TODO(dfc) can this be made a constant ?
-var (
- serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
- clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
-)
-
-// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
-// described in RFC 4253, section 6.4. direction should either be serverKeys
-// (to setup server->client keys) or clientKeys (for client->server keys).
-func (c *common) setupKeys(d direction, K, H, sessionId []byte, hashFunc crypto.Hash) error {
- cipherMode := cipherModes[c.cipherAlgo]
-
- macKeySize := 20
-
- iv := make([]byte, cipherMode.ivSize)
- key := make([]byte, cipherMode.keySize)
- macKey := make([]byte, macKeySize)
-
- h := hashFunc.New()
- generateKeyMaterial(iv, d.ivTag, K, H, sessionId, h)
- generateKeyMaterial(key, d.keyTag, K, H, sessionId, h)
- generateKeyMaterial(macKey, d.macKeyTag, K, H, sessionId, h)
-
- c.mac = truncatingMAC{12, hmac.New(sha1.New, macKey)}
-
- cipher, err := cipherMode.createCipher(key, iv)
- if err != nil {
- return err
- }
-
- c.cipher = cipher
-
- return nil
-}
-
-// generateKeyMaterial fills out with key material generated from tag, K, H
-// and sessionId, as specified in RFC 4253, section 7.2.
-func generateKeyMaterial(out, tag []byte, K, H, sessionId []byte, h hash.Hash) {
- var digestsSoFar []byte
-
- for len(out) > 0 {
- h.Reset()
- h.Write(K)
- h.Write(H)
-
- if len(digestsSoFar) == 0 {
- h.Write(tag)
- h.Write(sessionId)
- } else {
- h.Write(digestsSoFar)
- }
-
- digest := h.Sum(nil)
- n := copy(out, digest)
- out = out[n:]
- if len(out) > 0 {
- digestsSoFar = append(digestsSoFar, digest...)
- }
- }
-}
-
-// truncatingMAC wraps around a hash.Hash and truncates the output digest to
-// a given size.
-type truncatingMAC struct {
- length int
- hmac hash.Hash
-}
-
-func (t truncatingMAC) Write(data []byte) (int, error) {
- return t.hmac.Write(data)
-}
-
-func (t truncatingMAC) Sum(in []byte) []byte {
- out := t.hmac.Sum(in)
- return out[:len(in)+t.length]
-}
-
-func (t truncatingMAC) Reset() {
- t.hmac.Reset()
-}
-
-func (t truncatingMAC) Size() int {
- return t.length
-}
-
-func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
-
-// maxVersionStringBytes is the maximum number of bytes that we'll accept as a
-// version string. In the event that the client is talking a different protocol
-// we need to set a limit otherwise we will keep using more and more memory
-// while searching for the end of the version handshake.
-const maxVersionStringBytes = 1024
-
-// Read version string as specified by RFC 4253, section 4.2.
-func readVersion(r io.Reader) ([]byte, error) {
- versionString := make([]byte, 0, 64)
- var ok bool
- var buf [1]byte
-forEachByte:
- for len(versionString) < maxVersionStringBytes {
- _, err := io.ReadFull(r, buf[:])
- if err != nil {
- return nil, err
- }
- // The RFC says that the version should be terminated with \r\n
- // but several SSH servers actually only send a \n.
- if buf[0] == '\n' {
- ok = true
- break forEachByte
- }
- versionString = append(versionString, buf[0])
- }
-
- if !ok {
- return nil, errors.New("ssh: failed to read version string")
- }
-
- // There might be a '\r' on the end which we should remove.
- if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' {
- versionString = versionString[:len(versionString)-1]
- }
- return versionString, nil
-}
diff --git a/libgo/go/exp/ssh/transport_test.go b/libgo/go/exp/ssh/transport_test.go
deleted file mode 100644
index ab9177f0d11..00000000000
--- a/libgo/go/exp/ssh/transport_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-import (
- "bufio"
- "bytes"
- "testing"
-)
-
-func TestReadVersion(t *testing.T) {
- buf := serverVersion
- result, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf)))
- if err != nil {
- t.Errorf("readVersion didn't read version correctly: %s", err)
- }
- if !bytes.Equal(buf[:len(buf)-2], result) {
- t.Error("version read did not match expected")
- }
-}
-
-func TestReadVersionWithJustLF(t *testing.T) {
- var buf []byte
- buf = append(buf, serverVersion...)
- buf = buf[:len(buf)-1]
- buf[len(buf)-1] = '\n'
- result, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf)))
- if err != nil {
- t.Error("readVersion failed to handle just a \n")
- }
- if !bytes.Equal(buf[:len(buf)-1], result) {
- t.Errorf("version read did not match expected: got %x, want %x", result, buf[:len(buf)-1])
- }
-}
-
-func TestReadVersionTooLong(t *testing.T) {
- buf := make([]byte, maxVersionStringBytes+1)
- if _, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); err == nil {
- t.Errorf("readVersion consumed %d bytes without error", len(buf))
- }
-}
-
-func TestReadVersionWithoutCRLF(t *testing.T) {
- buf := serverVersion
- buf = buf[:len(buf)-1]
- if _, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); err == nil {
- t.Error("readVersion did not notice \\n was missing")
- }
-}
diff --git a/libgo/go/go/ast/import.go b/libgo/go/go/ast/import.go
index 894fecdaa7e..2d4f69aaea6 100644
--- a/libgo/go/go/ast/import.go
+++ b/libgo/go/go/ast/import.go
@@ -67,12 +67,7 @@ func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
// Record positions for specs.
pos := make([]posSpan, len(specs))
for i, s := range specs {
- // Cannot use s.End(), because it looks at len(s.Path.Value),
- // and that string might have gotten longer or shorter.
- // Instead, use s.Pos()+1, which is guaranteed to be > s.Pos()
- // and still before the original end of the string, since any
- // string literal must be at least 2 characters ("" or ``).
- pos[i] = posSpan{s.Pos(), s.Pos() + 1}
+ pos[i] = posSpan{s.Pos(), s.End()}
}
// Identify comments in this range.
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index 9515a7e6452..68e8d342005 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -5,245 +5,7 @@
// Package build provides tools for building Go packages.
package build
-import (
- "bytes"
- "errors"
- "fmt"
- "os"
- "os/exec"
- "path/filepath"
- "regexp"
- "runtime"
- "strings"
- "time"
-)
-
-// Build produces a build Script for the given package.
-func Build(tree *Tree, pkg string, info *DirInfo) (*Script, error) {
- s := &Script{}
- b := &build{
- script: s,
- path: filepath.Join(tree.SrcDir(), pkg),
- }
- b.obj = b.abs("_obj") + string(filepath.Separator)
-
- b.goarch = runtime.GOARCH
- if g := os.Getenv("GOARCH"); g != "" {
- b.goarch = g
- }
- var err error
- b.arch, err = ArchChar(b.goarch)
- if err != nil {
- return nil, err
- }
-
- // add import object files to list of Inputs
- for _, pkg := range info.Imports {
- t, p, err := FindTree(pkg)
- if err != nil && err != ErrNotFound {
- // FindTree should always be able to suggest an import
- // path and tree. The path must be malformed
- // (for example, an absolute or relative path).
- return nil, errors.New("build: invalid import: " + pkg)
- }
- s.addInput(filepath.Join(t.PkgDir(), p+".a"))
- }
-
- // .go files to be built with gc
- gofiles := b.abss(info.GoFiles...)
- s.addInput(gofiles...)
-
- var ofiles []string // object files to be linked or packed
-
- // make build directory
- b.mkdir(b.obj)
- s.addIntermediate(b.obj)
-
- // cgo
- if len(info.CgoFiles) > 0 {
- cgoFiles := b.abss(info.CgoFiles...)
- s.addInput(cgoFiles...)
- cgoCFiles := b.abss(info.CFiles...)
- s.addInput(cgoCFiles...)
- outGo, outObj := b.cgo(cgoFiles, cgoCFiles)
- gofiles = append(gofiles, outGo...)
- ofiles = append(ofiles, outObj...)
- s.addIntermediate(outGo...)
- s.addIntermediate(outObj...)
- }
-
- // compile
- if len(gofiles) > 0 {
- ofile := b.obj + "_go_." + b.arch
- b.gc(ofile, gofiles...)
- ofiles = append(ofiles, ofile)
- s.addIntermediate(ofile)
- }
-
- // assemble
- for _, sfile := range info.SFiles {
- ofile := b.obj + sfile[:len(sfile)-1] + b.arch
- sfile = b.abs(sfile)
- s.addInput(sfile)
- b.asm(ofile, sfile)
- ofiles = append(ofiles, ofile)
- s.addIntermediate(ofile)
- }
-
- if len(ofiles) == 0 {
- return nil, errors.New("make: no object files to build")
- }
-
- // choose target file
- var targ string
- if info.IsCommand() {
- // use the last part of the import path as binary name
- _, bin := filepath.Split(pkg)
- if runtime.GOOS == "windows" {
- bin += ".exe"
- }
- targ = filepath.Join(tree.BinDir(), bin)
- } else {
- targ = filepath.Join(tree.PkgDir(), pkg+".a")
- }
-
- // make target directory
- targDir, _ := filepath.Split(targ)
- b.mkdir(targDir)
-
- // link binary or pack object
- if info.IsCommand() {
- b.ld(targ, ofiles...)
- } else {
- b.gopack(targ, ofiles...)
- }
- s.Output = append(s.Output, targ)
-
- return b.script, nil
-}
-
-// A Script describes the build process for a Go package.
-// The Input, Intermediate, and Output fields are lists of absolute paths.
-type Script struct {
- Cmd []*Cmd
- Input []string
- Intermediate []string
- Output []string
-}
-
-func (s *Script) addInput(file ...string) {
- s.Input = append(s.Input, file...)
-}
-
-func (s *Script) addIntermediate(file ...string) {
- s.Intermediate = append(s.Intermediate, file...)
-}
-
-// Run runs the Script's Cmds in order.
-func (s *Script) Run() error {
- for _, c := range s.Cmd {
- if err := c.Run(); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Stale returns true if the build's inputs are newer than its outputs.
-func (s *Script) Stale() bool {
- var latest time.Time
- // get latest mtime of outputs
- for _, file := range s.Output {
- fi, err := os.Stat(file)
- if err != nil {
- // any error reading output files means stale
- return true
- }
- if mtime := fi.ModTime(); mtime.After(latest) {
- latest = mtime
- }
- }
- for _, file := range s.Input {
- fi, err := os.Stat(file)
- if err != nil || fi.ModTime().After(latest) {
- // any error reading input files means stale
- // (attempt to rebuild to figure out why)
- return true
- }
- }
- return false
-}
-
-// Clean removes the Script's Intermediate files.
-// It tries to remove every file and returns the first error it encounters.
-func (s *Script) Clean() (err error) {
- // Reverse order so that directories get removed after the files they contain.
- for i := len(s.Intermediate) - 1; i >= 0; i-- {
- if e := os.Remove(s.Intermediate[i]); err == nil {
- err = e
- }
- }
- return
-}
-
-// Nuke removes the Script's Intermediate and Output files.
-// It tries to remove every file and returns the first error it encounters.
-func (s *Script) Nuke() (err error) {
- // Reverse order so that directories get removed after the files they contain.
- for i := len(s.Output) - 1; i >= 0; i-- {
- if e := os.Remove(s.Output[i]); err == nil {
- err = e
- }
- }
- if e := s.Clean(); err == nil {
- err = e
- }
- return
-}
-
-// A Cmd describes an individual build command.
-type Cmd struct {
- Args []string // command-line
- Stdout string // write standard output to this file, "" is passthrough
- Dir string // working directory
- Env []string // environment
- Input []string // file paths (dependencies)
- Output []string // file paths
-}
-
-func (c *Cmd) String() string {
- return strings.Join(c.Args, " ")
-}
-
-// Run executes the Cmd.
-func (c *Cmd) Run() error {
- if c.Args[0] == "mkdir" {
- for _, p := range c.Output {
- if err := os.MkdirAll(p, 0777); err != nil {
- return fmt.Errorf("command %q: %v", c, err)
- }
- }
- return nil
- }
- out := new(bytes.Buffer)
- cmd := exec.Command(c.Args[0], c.Args[1:]...)
- cmd.Dir = c.Dir
- cmd.Env = c.Env
- cmd.Stdout = out
- cmd.Stderr = out
- if c.Stdout != "" {
- f, err := os.Create(c.Stdout)
- if err != nil {
- return err
- }
- defer f.Close()
- cmd.Stdout = f
- }
- if err := cmd.Run(); err != nil {
- return fmt.Errorf("command %q: %v\n%v", c, err, out)
- }
- return nil
-}
+import "errors"
// ArchChar returns the architecture character for the given goarch.
// For example, ArchChar("amd64") returns "6".
@@ -258,188 +20,3 @@ func ArchChar(goarch string) (string, error) {
}
return "", errors.New("unsupported GOARCH " + goarch)
}
-
-type build struct {
- script *Script
- path string
- obj string
- goarch string
- arch string
-}
-
-func (b *build) abs(file string) string {
- if filepath.IsAbs(file) {
- return file
- }
- return filepath.Join(b.path, file)
-}
-
-func (b *build) abss(file ...string) []string {
- s := make([]string, len(file))
- for i, f := range file {
- s[i] = b.abs(f)
- }
- return s
-}
-
-func (b *build) add(c Cmd) {
- b.script.Cmd = append(b.script.Cmd, &c)
-}
-
-func (b *build) mkdir(name string) {
- b.add(Cmd{
- Args: []string{"mkdir", "-p", name},
- Output: []string{name},
- })
-}
-
-func (b *build) gc(ofile string, gofiles ...string) {
- gc := b.arch + "g"
- args := append([]string{gc, "-o", ofile}, gcImportArgs...)
- args = append(args, gofiles...)
- b.add(Cmd{
- Args: args,
- Input: gofiles,
- Output: []string{ofile},
- })
-}
-
-func (b *build) asm(ofile string, sfile string) {
- asm := b.arch + "a"
- b.add(Cmd{
- Args: []string{asm, "-o", ofile, sfile},
- Input: []string{sfile},
- Output: []string{ofile},
- })
-}
-
-func (b *build) ld(targ string, ofiles ...string) {
- ld := b.arch + "l"
- args := append([]string{ld, "-o", targ}, ldImportArgs...)
- args = append(args, ofiles...)
- b.add(Cmd{
- Args: args,
- Input: ofiles,
- Output: []string{targ},
- })
-}
-
-func (b *build) gopack(targ string, ofiles ...string) {
- b.add(Cmd{
- Args: append([]string{"gopack", "grc", targ}, ofiles...),
- Input: ofiles,
- Output: []string{targ},
- })
-}
-
-func (b *build) cc(ofile string, cfiles ...string) {
- cc := b.arch + "c"
- dir := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
- inc := filepath.Join(runtime.GOROOT(), "pkg", dir)
- args := []string{cc, "-FVw", "-I", inc, "-o", ofile}
- b.add(Cmd{
- Args: append(args, cfiles...),
- Input: cfiles,
- Output: []string{ofile},
- })
-}
-
-func (b *build) gccCompile(ofile, cfile string) {
- b.add(Cmd{
- Args: b.gccArgs("-o", ofile, "-c", cfile),
- Input: []string{cfile},
- Output: []string{ofile},
- })
-}
-
-func (b *build) gccLink(ofile string, ofiles ...string) {
- b.add(Cmd{
- Args: append(b.gccArgs("-o", ofile), ofiles...),
- Input: ofiles,
- Output: []string{ofile},
- })
-}
-
-func (b *build) gccArgs(args ...string) []string {
- // TODO(adg): HOST_CC
- a := []string{"gcc", "-I", b.path, "-g", "-fPIC", "-O2"}
- switch b.arch {
- case "8":
- a = append(a, "-m32")
- case "6":
- a = append(a, "-m64")
- }
- return append(a, args...)
-}
-
-var cgoRe = regexp.MustCompile(`[/\\:]`)
-
-func (b *build) cgo(cgofiles, cgocfiles []string) (outGo, outObj []string) {
- // cgo
- // TODO(adg): CGOPKGPATH
- // TODO(adg): CGO_FLAGS
- gofiles := []string{b.obj + "_cgo_gotypes.go"}
- cfiles := []string{b.obj + "_cgo_main.c", b.obj + "_cgo_export.c"}
- for _, fn := range cgofiles {
- f := b.obj + cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
- gofiles = append(gofiles, f+"cgo1.go")
- cfiles = append(cfiles, f+"cgo2.c")
- }
- defunC := b.obj + "_cgo_defun.c"
- output := append([]string{defunC}, cfiles...)
- output = append(output, gofiles...)
- b.add(Cmd{
- Args: append([]string{"cgo", "--"}, cgofiles...),
- Dir: b.path,
- Env: append(os.Environ(), "GOARCH="+b.goarch),
- Input: cgofiles,
- Output: output,
- })
- outGo = append(outGo, gofiles...)
- b.script.addIntermediate(defunC, b.obj+"_cgo_export.h", b.obj+"_cgo_flags")
- b.script.addIntermediate(cfiles...)
-
- // cc _cgo_defun.c
- defunObj := b.obj + "_cgo_defun." + b.arch
- b.cc(defunObj, defunC)
- outObj = append(outObj, defunObj)
-
- // gcc
- linkobj := make([]string, 0, len(cfiles))
- for _, cfile := range cfiles {
- ofile := cfile[:len(cfile)-1] + "o"
- b.gccCompile(ofile, cfile)
- linkobj = append(linkobj, ofile)
- if !strings.HasSuffix(ofile, "_cgo_main.o") {
- outObj = append(outObj, ofile)
- } else {
- b.script.addIntermediate(ofile)
- }
- }
- for _, cfile := range cgocfiles {
- ofile := b.obj + cgoRe.ReplaceAllString(cfile[:len(cfile)-1], "_") + "o"
- b.gccCompile(ofile, cfile)
- linkobj = append(linkobj, ofile)
- outObj = append(outObj, ofile)
- }
- dynObj := b.obj + "_cgo_.o"
- b.gccLink(dynObj, linkobj...)
- b.script.addIntermediate(dynObj)
-
- // cgo -dynimport
- importC := b.obj + "_cgo_import.c"
- b.add(Cmd{
- Args: []string{"cgo", "-dynimport", dynObj},
- Stdout: importC,
- Input: []string{dynObj},
- Output: []string{importC},
- })
- b.script.addIntermediate(importC)
-
- // cc _cgo_import.ARCH
- importObj := b.obj + "_cgo_import." + b.arch
- b.cc(importObj, importC)
- outObj = append(outObj, importObj)
-
- return
-}
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index fd4030632a9..381e2b2d96a 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -5,7 +5,6 @@
package build
import (
- "os/exec"
"path/filepath"
"reflect"
"runtime"
@@ -63,8 +62,6 @@ func ifCgo(x []string) []string {
return nil
}
-const cmdtestOutput = "3"
-
func TestBuild(t *testing.T) {
for _, tt := range buildPkgs {
tree := Path[0] // Goroot
@@ -78,39 +75,32 @@ func TestBuild(t *testing.T) {
t.Errorf("ScanDir(%#q) = %#v, want %#v\n", tt.dir, info, tt.info)
continue
}
+ }
+}
- if tt.dir == "go/build/cgotest" && len(info.CgoFiles) == 0 {
- continue
- }
-
- s, err := Build(tree, tt.dir, info)
- if err != nil {
- t.Errorf("Build(%#q): %v", tt.dir, err)
- continue
+func TestMatch(t *testing.T) {
+ ctxt := DefaultContext
+ what := "default"
+ match := func(tag string) {
+ if !ctxt.match(tag) {
+ t.Errorf("%s context should match %s, does not", what, tag)
}
-
- if err := s.Run(); err != nil {
- t.Errorf("Run(%#q): %v", tt.dir, err)
- continue
+ }
+ nomatch := func(tag string) {
+ if ctxt.match(tag) {
+ t.Errorf("%s context should NOT match %s, does", what, tag)
}
+ }
- if tt.dir == "go/build/cmdtest" {
- bin := s.Output[0]
- b, err := exec.Command(bin).CombinedOutput()
- if err != nil {
- t.Errorf("exec %s: %v", bin, err)
- continue
- }
- if string(b) != cmdtestOutput {
- t.Errorf("cmdtest output: %s want: %s", b, cmdtestOutput)
- }
- }
+ match(runtime.GOOS + "," + runtime.GOARCH)
+ match(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
+ nomatch(runtime.GOOS + "," + runtime.GOARCH + ",foo")
- // Deferred because cmdtest depends on pkgtest.
- defer func(s *Script) {
- if err := s.Nuke(); err != nil {
- t.Errorf("nuking: %v", err)
- }
- }(s)
- }
+ what = "modified"
+ ctxt.BuildTags = []string{"foo"}
+ match(runtime.GOOS + "," + runtime.GOARCH)
+ match(runtime.GOOS + "," + runtime.GOARCH + ",foo")
+ nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
+ match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
+ nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
}
diff --git a/libgo/go/go/build/dir.go b/libgo/go/go/build/dir.go
index 5ce75fda7e0..d49846f7d4d 100644
--- a/libgo/go/go/build/dir.go
+++ b/libgo/go/go/build/dir.go
@@ -25,9 +25,10 @@ import (
// A Context specifies the supporting context for a build.
type Context struct {
- GOARCH string // target architecture
- GOOS string // target operating system
- CgoEnabled bool // whether cgo can be used
+ GOARCH string // target architecture
+ GOOS string // target operating system
+ CgoEnabled bool // whether cgo can be used
+ BuildTags []string // additional tags to recognize in +build lines
// By default, ScanDir uses the operating system's
// file system calls to read directories and files.
@@ -74,7 +75,7 @@ func (ctxt *Context) readFile(dir, file string) (string, []byte, error) {
// The DefaultContext is the default Context for builds.
// It uses the GOARCH and GOOS environment variables
// if set, or else the compiled code's GOARCH and GOOS.
-var DefaultContext = defaultContext()
+var DefaultContext Context = defaultContext()
var cgoEnabled = map[string]bool{
"darwin/386": true,
@@ -121,7 +122,7 @@ type DirInfo struct {
Imports []string // All packages imported by GoFiles
// Source files
- GoFiles []string // .go files in dir (excluding CgoFiles)
+ GoFiles []string // .go files in dir (excluding CgoFiles, TestGoFiles, XTestGoFiles)
HFiles []string // .h files in dir
CFiles []string // .c files in dir
SFiles []string // .s (and, when using cgo, .S files in dir)
@@ -148,13 +149,71 @@ func ScanDir(dir string) (info *DirInfo, err error) {
return DefaultContext.ScanDir(dir)
}
-// ScanDir returns a structure with details about the Go content found
-// in the given directory. The file lists exclude:
+// TODO(rsc): Move this comment to a more appropriate place.
+
+// ScanDir returns a structure with details about the Go package
+// found in the given directory.
+//
+// Most .go, .c, .h, and .s files in the directory are considered part
+// of the package. The exceptions are:
//
-// - files in package main (unless no other package is found)
-// - files in package documentation
-// - files ending in _test.go
+// - .go files in package main (unless no other package is found)
+// - .go files in package documentation
// - files starting with _ or .
+// - files with build constraints not satisfied by the context
+//
+// Build Constraints
+//
+// A build constraint is a line comment beginning with the directive +build
+// that lists the conditions under which a file should be included in the package.
+// Constraints may appear in any kind of source file (not just Go), but
+// they must be appear near the top of the file, preceded
+// only by blank lines and other line comments.
+//
+// A build constraint is evaluated as the OR of space-separated options;
+// each option evaluates as the AND of its comma-separated terms;
+// and each term is an alphanumeric word or, preceded by !, its negation.
+// That is, the build constraint:
+//
+// // +build linux,386 darwin,!cgo
+//
+// corresponds to the boolean formula:
+//
+// (linux AND 386) OR (darwin AND (NOT cgo))
+//
+// During a particular build, the following words are satisfied:
+//
+// - the target operating system, as spelled by runtime.GOOS
+// - the target architecture, as spelled by runtime.GOARCH
+// - "cgo", if ctxt.CgoEnabled is true
+// - any additional words listed in ctxt.BuildTags
+//
+// If a file's name, after stripping the extension and a possible _test suffix,
+// matches *_GOOS, *_GOARCH, or *_GOOS_GOARCH for any known operating
+// system and architecture values, then the file is considered to have an implicit
+// build constraint requiring those terms.
+//
+// Examples
+//
+// To keep a file from being considered for the build:
+//
+// // +build ignore
+//
+// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
+//
+// To build a file only when using cgo, and only on Linux and OS X:
+//
+// // +build linux,cgo darwin,cgo
+//
+// Such a file is usually paired with another file implementing the
+// default functionality for other systems, which in this case would
+// carry the constraint:
+//
+// // +build !linux !darwin !cgo
+//
+// Naming a file dns_windows.go will cause it to be included only when
+// building the package for Windows; similarly, math_386.s will be included
+// only when building the package for 32-bit x86.
//
func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
dirs, err := ctxt.readDir(dir)
@@ -389,7 +448,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
if f[0] == "+build" {
ok := false
for _, tok := range f[1:] {
- if ctxt.matchOSArch(tok) {
+ if ctxt.match(tok) {
ok = true
break
}
@@ -441,7 +500,7 @@ func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup)
if len(cond) > 0 {
ok := false
for _, c := range cond {
- if ctxt.matchOSArch(c) {
+ if ctxt.match(c) {
ok = true
break
}
@@ -550,26 +609,55 @@ func splitQuoted(s string) (r []string, err error) {
return args, err
}
-// matchOSArch returns true if the name is one of:
+// match returns true if the name is one of:
//
// $GOOS
// $GOARCH
// cgo (if cgo is enabled)
-// nocgo (if cgo is disabled)
+// !cgo (if cgo is disabled)
+// tag (if tag is listed in ctxt.BuildTags)
+// !tag (if tag is not listed in ctxt.BuildTags)
// a slash-separated list of any of these
//
-func (ctxt *Context) matchOSArch(name string) bool {
- if ctxt.CgoEnabled && name == "cgo" {
- return true
+func (ctxt *Context) match(name string) bool {
+ if name == "" {
+ return false
+ }
+ if i := strings.Index(name, ","); i >= 0 {
+ // comma-separated list
+ return ctxt.match(name[:i]) && ctxt.match(name[i+1:])
+ }
+ if strings.HasPrefix(name, "!!") { // bad syntax, reject always
+ return false
+ }
+ if strings.HasPrefix(name, "!") { // negation
+ return !ctxt.match(name[1:])
+ }
+
+ // Tags must be letters, digits, underscores.
+ // Unlike in Go identifiers, all digits is fine (e.g., "386").
+ for _, c := range name {
+ if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+ return false
+ }
}
- if !ctxt.CgoEnabled && name == "nocgo" {
+
+ // special tags
+ if ctxt.CgoEnabled && name == "cgo" {
return true
}
if name == ctxt.GOOS || name == ctxt.GOARCH {
return true
}
- i := strings.Index(name, "/")
- return i >= 0 && ctxt.matchOSArch(name[:i]) && ctxt.matchOSArch(name[i+1:])
+
+ // other tags
+ for _, tag := range ctxt.BuildTags {
+ if tag == name {
+ return true
+ }
+ }
+
+ return false
}
// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
diff --git a/libgo/go/go/build/path.go b/libgo/go/go/build/path.go
index b86f8288ea6..7e931faff19 100644
--- a/libgo/go/go/build/path.go
+++ b/libgo/go/go/build/path.go
@@ -7,7 +7,6 @@ package build
import (
"errors"
"fmt"
- "log"
"os"
"path/filepath"
"runtime"
@@ -81,7 +80,6 @@ func (t *Tree) HasPkg(pkg string) bool {
return false
}
return !fi.IsDir()
- // TODO(adg): check object version is consistent
}
var (
@@ -150,38 +148,20 @@ var (
func init() {
root := runtime.GOROOT()
t, err := newTree(root)
- if err != nil {
- log.Printf("invalid GOROOT %q: %v", root, err)
- } else {
+ if err == nil {
t.Goroot = true
Path = []*Tree{t}
}
-Loop:
for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
if p == "" {
continue
}
t, err := newTree(p)
if err != nil {
- log.Printf("invalid GOPATH %q: %v", p, err)
continue
}
- // Check for dupes.
- // TODO(alexbrainman): make this correct under windows (case insensitive).
- for _, t2 := range Path {
- if t2.Path != t.Path {
- continue
- }
- if t2.Goroot {
- log.Printf("GOPATH is the same as GOROOT: %q", t.Path)
- } else {
- log.Printf("duplicate GOPATH entry: %q", t.Path)
- }
- continue Loop
- }
-
Path = append(Path, t)
gcImportArgs = append(gcImportArgs, "-I", t.PkgDir())
ldImportArgs = append(ldImportArgs, "-L", t.PkgDir())
diff --git a/libgo/go/go/doc/doc.go b/libgo/go/go/doc/doc.go
index 0259a6fec9c..d4aae8ff05c 100644
--- a/libgo/go/go/doc/doc.go
+++ b/libgo/go/go/doc/doc.go
@@ -7,7 +7,7 @@ package doc
import (
"go/ast"
- "sort"
+ "go/token"
)
// Package is the documentation for an entire package.
@@ -17,11 +17,13 @@ type Package struct {
ImportPath string
Imports []string
Filenames []string
- Consts []*Value
- Types []*Type
- Vars []*Value
- Funcs []*Func
Bugs []string
+
+ // declarations
+ Consts []*Value
+ Types []*Type
+ Vars []*Value
+ Funcs []*Func
}
// Value is the documentation for a (possibly grouped) var or const declaration.
@@ -33,36 +35,30 @@ type Value struct {
order int
}
-type Method struct {
- *Func
- // TODO(gri) The following fields are not set at the moment.
- Origin *Type // original receiver base type
- Level int // embedding level; 0 means Func is not embedded
-}
-
-// Type is the documentation for type declaration.
+// Type is the documentation for a type declaration.
type Type struct {
- Doc string
- Name string
- Type *ast.TypeSpec
- Decl *ast.GenDecl
- Consts []*Value // sorted list of constants of (mostly) this type
- Vars []*Value // sorted list of variables of (mostly) this type
- Funcs []*Func // sorted list of functions returning this type
- Methods []*Method // sorted list of methods (including embedded ones) of this type
+ Doc string
+ Name string
+ Decl *ast.GenDecl
- methods []*Func // top-level methods only
- embedded methodSet // embedded methods only
- order int
+ // associated declarations
+ Consts []*Value // sorted list of constants of (mostly) this type
+ Vars []*Value // sorted list of variables of (mostly) this type
+ Funcs []*Func // sorted list of functions returning this type
+ Methods []*Func // sorted list of methods (including embedded ones) of this type
}
// Func is the documentation for a func declaration.
type Func struct {
Doc string
Name string
- // TODO(gri) remove Recv once we switch to new implementation
- Recv ast.Expr // TODO(rsc): Would like string here
Decl *ast.FuncDecl
+
+ // methods
+ // (for functions, these fields have the respective zero value)
+ Recv string // actual receiver "T" or "*T"
+ Orig string // original receiver "T" or "*T"
+ Level int // embedding level; 0 means not embedded
}
// Mode values control the operation of New.
@@ -74,27 +70,24 @@ const (
AllDecls Mode = 1 << iota
)
-// New computes the package documentation for the given package.
-func New(pkg *ast.Package, importpath string, mode Mode) *Package {
- var r docReader
- r.init(pkg.Name, mode)
- filenames := make([]string, len(pkg.Files))
- // sort package files before reading them so that the
- // result is the same on different machines (32/64bit)
- i := 0
- for filename := range pkg.Files {
- filenames[i] = filename
- i++
- }
- sort.Strings(filenames)
-
- // process files in sorted order
- for _, filename := range filenames {
- f := pkg.Files[filename]
- if mode&AllDecls == 0 {
- r.fileExports(f)
- }
- r.addFile(f)
+// New computes the package documentation for the given package AST.
+// New takes ownership of the AST pkg and may edit or overwrite it.
+//
+func New(pkg *ast.Package, importPath string, mode Mode) *Package {
+ var r reader
+ r.readPackage(pkg, mode)
+ r.computeMethodSets()
+ r.cleanupTypes()
+ return &Package{
+ Doc: r.doc,
+ Name: pkg.Name,
+ ImportPath: importPath,
+ Imports: sortedKeys(r.imports),
+ Filenames: r.filenames,
+ Bugs: r.bugs,
+ Consts: sortedValues(r.values, token.CONST),
+ Types: sortedTypes(r.types),
+ Vars: sortedValues(r.values, token.VAR),
+ Funcs: sortedFuncs(r.funcs),
}
- return r.newDoc(importpath, filenames)
}
diff --git a/libgo/go/go/doc/doc_test.go b/libgo/go/go/doc/doc_test.go
index 0a4830148af..d9ffe47b614 100644
--- a/libgo/go/go/doc/doc_test.go
+++ b/libgo/go/go/doc/doc_test.go
@@ -7,6 +7,7 @@ package doc
import (
"bytes"
"flag"
+ "fmt"
"go/parser"
"go/printer"
"go/token"
@@ -64,7 +65,7 @@ type bundle struct {
FSet *token.FileSet
}
-func Test(t *testing.T) {
+func test(t *testing.T, mode Mode) {
// get all packages
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, dataDir, isGoFile, parser.ParseComments)
@@ -75,7 +76,7 @@ func Test(t *testing.T) {
// test all packages
for _, pkg := range pkgs {
importpath := dataDir + "/" + pkg.Name
- doc := New(pkg, importpath, 0)
+ doc := New(pkg, importpath, mode)
// golden files always use / in filenames - canonicalize them
for i, filename := range doc.Filenames {
@@ -91,7 +92,7 @@ func Test(t *testing.T) {
got := buf.Bytes()
// update golden file if necessary
- golden := filepath.Join(dataDir, pkg.Name+".out")
+ golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
if *update {
err := ioutil.WriteFile(golden, got, 0644)
if err != nil {
@@ -113,3 +114,8 @@ func Test(t *testing.T) {
}
}
}
+
+func Test(t *testing.T) {
+ test(t, 0)
+ test(t, AllDecls)
+}
diff --git a/libgo/go/go/doc/exports.go b/libgo/go/go/doc/exports.go
index a35b3e23914..e6f58ccb350 100644
--- a/libgo/go/go/doc/exports.go
+++ b/libgo/go/go/doc/exports.go
@@ -8,6 +8,9 @@ package doc
import "go/ast"
+// filterIdentList removes unexported names from list in place
+// and returns the resulting list.
+//
func filterIdentList(list []*ast.Ident) []*ast.Ident {
j := 0
for _, x := range list {
@@ -19,54 +22,46 @@ func filterIdentList(list []*ast.Ident) []*ast.Ident {
return list[0:j]
}
-func baseName(x ast.Expr) *ast.Ident {
- switch t := x.(type) {
- case *ast.Ident:
- return t
- case *ast.SelectorExpr:
- if _, ok := t.X.(*ast.Ident); ok {
- return t.Sel
- }
- case *ast.StarExpr:
- return baseName(t.X)
- }
- return nil
-}
-
-func (doc *docReader) filterFieldList(tinfo *typeInfo, fields *ast.FieldList) (removedFields bool) {
+// filterFieldList removes unexported fields (field names) from the field list
+// in place and returns true if fields were removed. Removed fields that are
+// anonymous (embedded) fields are added as embedded types to base. filterType
+// is called with the types of all remaining fields.
+//
+func (r *reader) filterFieldList(base *baseType, fields *ast.FieldList) (removedFields bool) {
if fields == nil {
- return false
+ return
}
list := fields.List
j := 0
- for _, f := range list {
+ for _, field := range list {
keepField := false
- if len(f.Names) == 0 {
+ if n := len(field.Names); n == 0 {
// anonymous field
- name := baseName(f.Type)
- if name != nil && name.IsExported() {
- // we keep the field - in this case doc.addDecl
+ name, imp := baseTypeName(field.Type)
+ if ast.IsExported(name) {
+ // we keep the field - in this case r.readDecl
// will take care of adding the embedded type
keepField = true
- } else if tinfo != nil {
+ } else if base != nil && !imp {
// we don't keep the field - add it as an embedded
// type so we won't loose its methods, if any
- if embedded := doc.lookupTypeInfo(name.Name); embedded != nil {
- _, ptr := f.Type.(*ast.StarExpr)
- tinfo.addEmbeddedType(embedded, ptr)
+ if embedded := r.lookupType(name); embedded != nil {
+ _, ptr := field.Type.(*ast.StarExpr)
+ base.addEmbeddedType(embedded, ptr)
}
}
} else {
- n := len(f.Names)
- f.Names = filterIdentList(f.Names)
- if len(f.Names) < n {
+ field.Names = filterIdentList(field.Names)
+ if len(field.Names) < n {
removedFields = true
}
- keepField = len(f.Names) > 0
+ if len(field.Names) > 0 {
+ keepField = true
+ }
}
if keepField {
- doc.filterType(nil, f.Type)
- list[j] = f
+ r.filterType(nil, field.Type)
+ list[j] = field
j++
}
}
@@ -77,52 +72,48 @@ func (doc *docReader) filterFieldList(tinfo *typeInfo, fields *ast.FieldList) (r
return
}
-func (doc *docReader) filterParamList(fields *ast.FieldList) bool {
- if fields == nil {
- return false
- }
- var b bool
- for _, f := range fields.List {
- if doc.filterType(nil, f.Type) {
- b = true
+// filterParamList applies filterType to each parameter type in fields.
+//
+func (r *reader) filterParamList(fields *ast.FieldList) {
+ if fields != nil {
+ for _, f := range fields.List {
+ r.filterType(nil, f.Type)
}
}
- return b
}
-func (doc *docReader) filterType(tinfo *typeInfo, typ ast.Expr) bool {
+// filterType strips any unexported struct fields or method types from typ
+// in place. If fields (or methods) have been removed, the corresponding
+// struct or interface type has the Incomplete field set to true.
+//
+func (r *reader) filterType(base *baseType, typ ast.Expr) {
switch t := typ.(type) {
case *ast.Ident:
- return ast.IsExported(t.Name)
+ // nothing to do
case *ast.ParenExpr:
- return doc.filterType(nil, t.X)
+ r.filterType(nil, t.X)
case *ast.ArrayType:
- return doc.filterType(nil, t.Elt)
+ r.filterType(nil, t.Elt)
case *ast.StructType:
- if doc.filterFieldList(tinfo, t.Fields) {
+ if r.filterFieldList(base, t.Fields) {
t.Incomplete = true
}
- return len(t.Fields.List) > 0
case *ast.FuncType:
- b1 := doc.filterParamList(t.Params)
- b2 := doc.filterParamList(t.Results)
- return b1 || b2
+ r.filterParamList(t.Params)
+ r.filterParamList(t.Results)
case *ast.InterfaceType:
- if doc.filterFieldList(tinfo, t.Methods) {
+ if r.filterFieldList(base, t.Methods) {
t.Incomplete = true
}
- return len(t.Methods.List) > 0
case *ast.MapType:
- b1 := doc.filterType(nil, t.Key)
- b2 := doc.filterType(nil, t.Value)
- return b1 || b2
+ r.filterType(nil, t.Key)
+ r.filterType(nil, t.Value)
case *ast.ChanType:
- return doc.filterType(nil, t.Value)
+ r.filterType(nil, t.Value)
}
- return false
}
-func (doc *docReader) filterSpec(spec ast.Spec) bool {
+func (r *reader) filterSpec(spec ast.Spec) bool {
switch s := spec.(type) {
case *ast.ImportSpec:
// always keep imports so we can collect them
@@ -130,22 +121,22 @@ func (doc *docReader) filterSpec(spec ast.Spec) bool {
case *ast.ValueSpec:
s.Names = filterIdentList(s.Names)
if len(s.Names) > 0 {
- doc.filterType(nil, s.Type)
+ r.filterType(nil, s.Type)
return true
}
case *ast.TypeSpec:
if ast.IsExported(s.Name.Name) {
- doc.filterType(doc.lookupTypeInfo(s.Name.Name), s.Type)
+ r.filterType(r.lookupType(s.Name.Name), s.Type)
return true
}
}
return false
}
-func (doc *docReader) filterSpecList(list []ast.Spec) []ast.Spec {
+func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec {
j := 0
for _, s := range list {
- if doc.filterSpec(s) {
+ if r.filterSpec(s) {
list[j] = s
j++
}
@@ -153,10 +144,10 @@ func (doc *docReader) filterSpecList(list []ast.Spec) []ast.Spec {
return list[0:j]
}
-func (doc *docReader) filterDecl(decl ast.Decl) bool {
+func (r *reader) filterDecl(decl ast.Decl) bool {
switch d := decl.(type) {
case *ast.GenDecl:
- d.Specs = doc.filterSpecList(d.Specs)
+ d.Specs = r.filterSpecList(d.Specs)
return len(d.Specs) > 0
case *ast.FuncDecl:
return ast.IsExported(d.Name.Name)
@@ -164,18 +155,15 @@ func (doc *docReader) filterDecl(decl ast.Decl) bool {
return false
}
-// fileExports trims the AST for a Go file in place such that
-// only exported nodes remain. fileExports returns true if
-// there are exported declarations; otherwise it returns false.
+// fileExports removes unexported declarations from src in place.
//
-func (doc *docReader) fileExports(src *ast.File) bool {
+func (r *reader) fileExports(src *ast.File) {
j := 0
for _, d := range src.Decls {
- if doc.filterDecl(d) {
+ if r.filterDecl(d) {
src.Decls[j] = d
j++
}
}
src.Decls = src.Decls[0:j]
- return j > 0
}
diff --git a/libgo/go/go/doc/filter.go b/libgo/go/go/doc/filter.go
index fe2d39b8802..02b66ccefaf 100644
--- a/libgo/go/go/doc/filter.go
+++ b/libgo/go/go/doc/filter.go
@@ -71,17 +71,6 @@ func filterFuncs(a []*Func, f Filter) []*Func {
return a[0:w]
}
-func filterMethods(a []*Method, f Filter) []*Method {
- w := 0
- for _, md := range a {
- if f(md.Name) {
- a[w] = md
- w++
- }
- }
- return a[0:w]
-}
-
func filterTypes(a []*Type, f Filter) []*Type {
w := 0
for _, td := range a {
@@ -93,7 +82,7 @@ func filterTypes(a []*Type, f Filter) []*Type {
td.Consts = filterValues(td.Consts, f)
td.Vars = filterValues(td.Vars, f)
td.Funcs = filterFuncs(td.Funcs, f)
- td.Methods = filterMethods(td.Methods, f)
+ td.Methods = filterFuncs(td.Methods, f)
n += len(td.Consts) + len(td.Vars) + len(td.Funcs) + len(td.Methods)
}
if n > 0 {
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index 1a2fad559a6..9c6f0816b60 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -13,112 +13,208 @@ import (
)
// ----------------------------------------------------------------------------
-// Collection of documentation info
+// function/method sets
+//
+// Internally, we treat functions like methods and collect them in method sets.
+
+// methodSet describes a set of methods. Entries where Decl == nil are conflict
+// entries (more then one method with the same name at the same embedding level).
+//
+type methodSet map[string]*Func
+
+// recvString returns a string representation of recv of the
+// form "T", "*T", or "BADRECV" (if not a proper receiver type).
+//
+func recvString(recv ast.Expr) string {
+ switch t := recv.(type) {
+ case *ast.Ident:
+ return t.Name
+ case *ast.StarExpr:
+ return "*" + recvString(t.X)
+ }
+ return "BADRECV"
+}
+
+// set creates the corresponding Func for f and adds it to mset.
+// If there are multiple f's with the same name, set keeps the first
+// one with documentation; conflicts are ignored.
+//
+func (mset methodSet) set(f *ast.FuncDecl) {
+ name := f.Name.Name
+ if g := mset[name]; g != nil && g.Doc != "" {
+ // A function with the same name has already been registered;
+ // since it has documentation, assume f is simply another
+ // implementation and ignore it. This does not happen if the
+ // caller is using go/build.ScanDir to determine the list of
+ // files implementing a package.
+ return
+ }
+ // function doesn't exist or has no documentation; use f
+ recv := ""
+ if f.Recv != nil {
+ var typ ast.Expr
+ // be careful in case of incorrect ASTs
+ if list := f.Recv.List; len(list) == 1 {
+ typ = list[0].Type
+ }
+ recv = recvString(typ)
+ }
+ mset[name] = &Func{
+ Doc: f.Doc.Text(),
+ Name: name,
+ Decl: f,
+ Recv: recv,
+ Orig: recv,
+ }
+ f.Doc = nil // doc consumed - remove from AST
+}
+
+// add adds method m to the method set; m is ignored if the method set
+// already contains a method with the same name at the same or a higher
+// level then m.
+//
+func (mset methodSet) add(m *Func) {
+ old := mset[m.Name]
+ if old == nil || m.Level < old.Level {
+ mset[m.Name] = m
+ return
+ }
+ if old != nil && m.Level == old.Level {
+ // conflict - mark it using a method with nil Decl
+ mset[m.Name] = &Func{
+ Name: m.Name,
+ Level: m.Level,
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Base types
+
+// baseTypeName returns the name of the base type of x (or "")
+// and whether the type is imported or not.
+//
+func baseTypeName(x ast.Expr) (name string, imported bool) {
+ switch t := x.(type) {
+ case *ast.Ident:
+ return t.Name, false
+ case *ast.SelectorExpr:
+ if _, ok := t.X.(*ast.Ident); ok {
+ // only possible for qualified type names;
+ // assume type is imported
+ return t.Sel.Name, true
+ }
+ case *ast.StarExpr:
+ return baseTypeName(t.X)
+ }
+ return
+}
// embeddedType describes the type of an anonymous field.
//
type embeddedType struct {
- typ *typeInfo // the corresponding base type
+ typ *baseType // the corresponding base type
ptr bool // if set, the anonymous field type is a pointer
}
-type typeInfo struct {
- name string // base type name
- isStruct bool
- // len(decl.Specs) == 1, and the element type is *ast.TypeSpec
- // if the type declaration hasn't been seen yet, decl is nil
- decl *ast.GenDecl
- embedded []embeddedType
- forward *Type // forward link to processed type documentation
-
- // declarations associated with the type
- values []*ast.GenDecl // consts and vars
- factories map[string]*ast.FuncDecl
- methods map[string]*ast.FuncDecl
-}
+type baseType struct {
+ doc string // doc comment for type
+ name string // local type name (excluding package qualifier)
+ decl *ast.GenDecl // nil if declaration hasn't been seen yet
-func (info *typeInfo) exported() bool {
- return ast.IsExported(info.name)
+ // associated declarations
+ values []*Value // consts and vars
+ funcs methodSet
+ methods methodSet
+
+ isEmbedded bool // true if this type is embedded
+ isStruct bool // true if this type is a struct
+ embedded []embeddedType // list of embedded types
}
-func (info *typeInfo) addEmbeddedType(embedded *typeInfo, isPtr bool) {
- info.embedded = append(info.embedded, embeddedType{embedded, isPtr})
+func (typ *baseType) addEmbeddedType(e *baseType, isPtr bool) {
+ e.isEmbedded = true
+ typ.embedded = append(typ.embedded, embeddedType{e, isPtr})
}
-// docReader accumulates documentation for a single package.
+// ----------------------------------------------------------------------------
+// AST reader
+
+// reader accumulates documentation for a single package.
// It modifies the AST: Comments (declaration documentation)
-// that have been collected by the DocReader are set to nil
+// that have been collected by the reader are set to nil
// in the respective AST nodes so that they are not printed
// twice (once when printing the documentation and once when
// printing the corresponding AST node).
//
-type docReader struct {
- doc *ast.CommentGroup // package documentation, if any
- pkgName string
- mode Mode
- imports map[string]int
- values []*ast.GenDecl // consts and vars
- types map[string]*typeInfo
- embedded map[string]*typeInfo // embedded types, possibly not exported
- funcs map[string]*ast.FuncDecl
- bugs []*ast.CommentGroup
+type reader struct {
+ mode Mode
+
+ // package properties
+ doc string // package documentation, if any
+ filenames []string
+ bugs []string
+
+ // declarations
+ imports map[string]int
+ values []*Value // consts and vars
+ types map[string]*baseType
+ funcs methodSet
}
-func (doc *docReader) init(pkgName string, mode Mode) {
- doc.pkgName = pkgName
- doc.mode = mode
- doc.imports = make(map[string]int)
- doc.types = make(map[string]*typeInfo)
- doc.embedded = make(map[string]*typeInfo)
- doc.funcs = make(map[string]*ast.FuncDecl)
-}
-
-func (doc *docReader) addDoc(comments *ast.CommentGroup) {
- if doc.doc == nil {
- // common case: just one package comment
- doc.doc = comments
- return
- }
- // More than one package comment: Usually there will be only
- // one file with a package comment, but it's better to collect
- // all comments than drop them on the floor.
- blankComment := &ast.Comment{token.NoPos, "//"}
- list := append(doc.doc.List, blankComment)
- doc.doc.List = append(list, comments.List...)
+// isVisible reports whether name is visible in the documentation.
+//
+func (r *reader) isVisible(name string) bool {
+ return r.mode&AllDecls != 0 || ast.IsExported(name)
}
-func (doc *docReader) lookupTypeInfo(name string) *typeInfo {
+// lookupType returns the base type with the given name.
+// If the base type has not been encountered yet, a new
+// type with the given name but no associated declaration
+// is added to the type map.
+//
+func (r *reader) lookupType(name string) *baseType {
if name == "" || name == "_" {
return nil // no type docs for anonymous types
}
- if info, found := doc.types[name]; found {
- return info
+ if typ, found := r.types[name]; found {
+ return typ
}
- // type wasn't found - add one without declaration
- info := &typeInfo{
- name: name,
- factories: make(map[string]*ast.FuncDecl),
- methods: make(map[string]*ast.FuncDecl),
+ // type not found - add one without declaration
+ typ := &baseType{
+ name: name,
+ funcs: make(methodSet),
+ methods: make(methodSet),
}
- doc.types[name] = info
- return info
+ r.types[name] = typ
+ return typ
}
-func baseTypeName(typ ast.Expr, allTypes bool) string {
- switch t := typ.(type) {
- case *ast.Ident:
- // if the type is not exported, the effect to
- // a client is as if there were no type name
- if t.IsExported() || allTypes {
- return t.Name
+func (r *reader) readDoc(comment *ast.CommentGroup) {
+ // By convention there should be only one package comment
+ // but collect all of them if there are more then one.
+ text := comment.Text()
+ if r.doc == "" {
+ r.doc = text
+ return
+ }
+ r.doc += "\n" + text
+}
+
+func specNames(specs []ast.Spec) []string {
+ names := make([]string, 0, len(specs)) // reasonable estimate
+ for _, s := range specs {
+ // s guaranteed to be an *ast.ValueSpec by readValue
+ for _, ident := range s.(*ast.ValueSpec).Names {
+ names = append(names, ident.Name)
}
- case *ast.StarExpr:
- return baseTypeName(t.X, allTypes)
}
- return ""
+ return names
}
-func (doc *docReader) addValue(decl *ast.GenDecl) {
+// readValue processes a const or var declaration.
+//
+func (r *reader) readValue(decl *ast.GenDecl) {
// determine if decl should be associated with a type
// Heuristic: For each typed entry, determine the type name, if any.
// If there is exactly one type name that is sufficiently
@@ -126,91 +222,156 @@ func (doc *docReader) addValue(decl *ast.GenDecl) {
domName := ""
domFreq := 0
prev := ""
- for _, s := range decl.Specs {
- if v, ok := s.(*ast.ValueSpec); ok {
- name := ""
- switch {
- case v.Type != nil:
- // a type is present; determine its name
- name = baseTypeName(v.Type, false)
- case decl.Tok == token.CONST:
- // no type is present but we have a constant declaration;
- // use the previous type name (w/o more type information
- // we cannot handle the case of unnamed variables with
- // initializer expressions except for some trivial cases)
- name = prev
+ n := 0
+ for _, spec := range decl.Specs {
+ s, ok := spec.(*ast.ValueSpec)
+ if !ok {
+ continue // should not happen, but be conservative
+ }
+ name := ""
+ switch {
+ case s.Type != nil:
+ // a type is present; determine its name
+ if n, imp := baseTypeName(s.Type); !imp && r.isVisible(n) {
+ name = n
}
- if name != "" {
- // entry has a named type
- if domName != "" && domName != name {
- // more than one type name - do not associate
- // with any type
- domName = ""
- break
- }
- domName = name
- domFreq++
+ case decl.Tok == token.CONST:
+ // no type is present but we have a constant declaration;
+ // use the previous type name (w/o more type information
+ // we cannot handle the case of unnamed variables with
+ // initializer expressions except for some trivial cases)
+ name = prev
+ }
+ if name != "" {
+ // entry has a named type
+ if domName != "" && domName != name {
+ // more than one type name - do not associate
+ // with any type
+ domName = ""
+ break
}
- prev = name
+ domName = name
+ domFreq++
}
+ prev = name
+ n++
+ }
+
+ // nothing to do w/o a legal declaration
+ if n == 0 {
+ return
}
- // determine values list
+ // determine values list with which to associate the Value for this decl
+ values := &r.values
const threshold = 0.75
- values := &doc.values
if domName != "" && domFreq >= int(float64(len(decl.Specs))*threshold) {
// typed entries are sufficiently frequent
- typ := doc.lookupTypeInfo(domName)
+ typ := r.lookupType(domName)
if typ != nil {
values = &typ.values // associate with that type
}
}
- *values = append(*values, decl)
+ *values = append(*values, &Value{
+ Doc: decl.Doc.Text(),
+ Names: specNames(decl.Specs),
+ Decl: decl,
+ order: len(*values),
+ })
+ decl.Doc = nil // doc consumed - remove from AST
}
-// Helper function to set the table entry for function f. Makes sure that
-// at least one f with associated documentation is stored in table, if there
-// are multiple f's with the same name.
-func setFunc(table map[string]*ast.FuncDecl, f *ast.FuncDecl) {
- name := f.Name.Name
- if g, exists := table[name]; exists && g.Doc != nil {
- // a function with the same name has already been registered;
- // since it has documentation, assume f is simply another
- // implementation and ignore it
- // TODO(gri) consider collecting all functions, or at least
- // all comments
- return
+// fields returns a struct's fields or an interface's methods.
+//
+func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) {
+ var fields *ast.FieldList
+ switch t := typ.(type) {
+ case *ast.StructType:
+ fields = t.Fields
+ isStruct = true
+ case *ast.InterfaceType:
+ fields = t.Methods
+ }
+ if fields != nil {
+ list = fields.List
+ }
+ return
+}
+
+// readType processes a type declaration.
+//
+func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
+ typ := r.lookupType(spec.Name.Name)
+ if typ == nil {
+ return // no name or blank name - ignore the type
+ }
+
+ // A type should be added at most once, so info.decl
+ // should be nil - if it is not, simply overwrite it.
+ typ.decl = decl
+
+ // compute documentation
+ doc := spec.Doc
+ spec.Doc = nil // doc consumed - remove from AST
+ if doc == nil {
+ // no doc associated with the spec, use the declaration doc, if any
+ doc = decl.Doc
+ }
+ decl.Doc = nil // doc consumed - remove from AST
+ typ.doc = doc.Text()
+
+ // look for anonymous fields that might contribute methods
+ var list []*ast.Field
+ list, typ.isStruct = fields(spec.Type)
+ for _, field := range list {
+ if len(field.Names) == 0 {
+ // anonymous field - add corresponding field type to typ
+ n, imp := baseTypeName(field.Type)
+ if imp {
+ // imported type - we don't handle this case
+ // at the moment
+ return
+ }
+ if embedded := r.lookupType(n); embedded != nil {
+ _, ptr := field.Type.(*ast.StarExpr)
+ typ.addEmbeddedType(embedded, ptr)
+ }
+ }
}
- // function doesn't exist or has no documentation; use f
- table[name] = f
}
-func (doc *docReader) addFunc(fun *ast.FuncDecl) {
+// readFunc processes a func or method declaration.
+//
+func (r *reader) readFunc(fun *ast.FuncDecl) {
// strip function body
fun.Body = nil
// determine if it should be associated with a type
if fun.Recv != nil {
// method
- recvTypeName := baseTypeName(fun.Recv.List[0].Type, true /* exported or not */ )
- var typ *typeInfo
- if ast.IsExported(recvTypeName) {
- // exported recv type: if not found, add it to doc.types
- typ = doc.lookupTypeInfo(recvTypeName)
+ recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
+ if imp {
+ // should not happen (incorrect AST);
+ // don't show this method
+ return
+ }
+ var typ *baseType
+ if r.isVisible(recvTypeName) {
+ // visible recv type: if not found, add it to r.types
+ typ = r.lookupType(recvTypeName)
} else {
- // unexported recv type: if not found, do not add it
- // (unexported embedded types are added before this
+ // invisible recv type: if not found, do not add it
+ // (invisible embedded types are added before this
// phase, so if the type doesn't exist yet, we don't
// care about this method)
- typ = doc.types[recvTypeName]
+ typ = r.types[recvTypeName]
}
if typ != nil {
- // exported receiver type
// associate method with the type
// (if the type is not exported, it may be embedded
// somewhere so we need to collect the method anyway)
- setFunc(typ.methods, fun)
+ typ.methods.set(fun)
}
// otherwise don't show the method
// TODO(gri): There may be exported methods of non-exported types
@@ -228,113 +389,70 @@ func (doc *docReader) addFunc(fun *ast.FuncDecl) {
// exactly one (named or anonymous) result associated
// with the first type in result signature (there may
// be more than one result)
- tname := baseTypeName(res.Type, false)
- typ := doc.lookupTypeInfo(tname)
- if typ != nil {
- // named and exported result type
- setFunc(typ.factories, fun)
- return
+ if n, imp := baseTypeName(res.Type); !imp && r.isVisible(n) {
+ if typ := r.lookupType(n); typ != nil {
+ // associate Func with typ
+ typ.funcs.set(fun)
+ return
+ }
}
}
}
- // ordinary function
- setFunc(doc.funcs, fun)
+ // just an ordinary function
+ r.funcs.set(fun)
}
-func (doc *docReader) addDecl(decl ast.Decl) {
- switch d := decl.(type) {
- case *ast.GenDecl:
- if len(d.Specs) > 0 {
+var (
+ bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
+ bug_content = regexp.MustCompile("[^ \n\r\t]+") // at least one non-whitespace char
+)
+
+// readFile adds the AST for a source file to the reader.
+//
+func (r *reader) readFile(src *ast.File) {
+ // add package documentation
+ if src.Doc != nil {
+ r.readDoc(src.Doc)
+ src.Doc = nil // doc consumed - remove from AST
+ }
+
+ // add all declarations
+ for _, decl := range src.Decls {
+ switch d := decl.(type) {
+ case *ast.GenDecl:
switch d.Tok {
case token.IMPORT:
// imports are handled individually
for _, spec := range d.Specs {
- if import_, err := strconv.Unquote(spec.(*ast.ImportSpec).Path.Value); err == nil {
- doc.imports[import_] = 1
+ if s, ok := spec.(*ast.ImportSpec); ok {
+ if import_, err := strconv.Unquote(s.Path.Value); err == nil {
+ r.imports[import_] = 1
+ }
}
}
case token.CONST, token.VAR:
// constants and variables are always handled as a group
- doc.addValue(d)
+ r.readValue(d)
case token.TYPE:
// types are handled individually
for _, spec := range d.Specs {
- tspec := spec.(*ast.TypeSpec)
- // add the type to the documentation
- info := doc.lookupTypeInfo(tspec.Name.Name)
- if info == nil {
- continue // no name - ignore the type
- }
- // Make a (fake) GenDecl node for this TypeSpec
- // (we need to do this here - as opposed to just
- // for printing - so we don't lose the GenDecl
- // documentation). Since a new GenDecl node is
- // created, there's no need to nil out d.Doc.
- //
- // TODO(gri): Consider just collecting the TypeSpec
- // node (and copy in the GenDecl.doc if there is no
- // doc in the TypeSpec - this is currently done in
- // makeTypes below). Simpler data structures, but
- // would lose GenDecl documentation if the TypeSpec
- // has documentation as well.
- fake := &ast.GenDecl{d.Doc, d.Pos(), token.TYPE, token.NoPos,
- []ast.Spec{tspec}, token.NoPos}
- // A type should be added at most once, so info.decl
- // should be nil - if it isn't, simply overwrite it.
- info.decl = fake
- // Look for anonymous fields that might contribute methods.
- var fields *ast.FieldList
- switch typ := spec.(*ast.TypeSpec).Type.(type) {
- case *ast.StructType:
- fields = typ.Fields
- info.isStruct = true
- case *ast.InterfaceType:
- fields = typ.Methods
- }
- if fields != nil {
- for _, field := range fields.List {
- if len(field.Names) == 0 {
- // anonymous field - add corresponding type
- // to the info and collect it in doc
- name := baseTypeName(field.Type, true)
- if embedded := doc.lookupTypeInfo(name); embedded != nil {
- _, ptr := field.Type.(*ast.StarExpr)
- info.addEmbeddedType(embedded, ptr)
- }
- }
+ if s, ok := spec.(*ast.TypeSpec); ok {
+ // use an individual (possibly fake) declaration
+ // for each type; this also ensures that each type
+ // gets to (re-)use the declaration documentation
+ // if there's none associated with the spec itself
+ fake := &ast.GenDecl{
+ d.Doc, d.Pos(), token.TYPE, token.NoPos,
+ []ast.Spec{s}, token.NoPos,
}
+ r.readType(fake, s)
}
}
}
+ case *ast.FuncDecl:
+ r.readFunc(d)
}
- case *ast.FuncDecl:
- doc.addFunc(d)
- }
-}
-
-func copyCommentList(list []*ast.Comment) []*ast.Comment {
- return append([]*ast.Comment(nil), list...)
-}
-
-var (
- bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
- bug_content = regexp.MustCompile("[^ \n\r\t]+") // at least one non-whitespace char
-)
-
-// addFile adds the AST for a source file to the docReader.
-// Adding the same AST multiple times is a no-op.
-//
-func (doc *docReader) addFile(src *ast.File) {
- // add package documentation
- if src.Doc != nil {
- doc.addDoc(src.Doc)
- src.Doc = nil // doc consumed - remove from ast.File node
- }
-
- // add all declarations
- for _, decl := range src.Decls {
- doc.addDecl(decl)
}
// collect BUG(...) comments
@@ -344,348 +462,273 @@ func (doc *docReader) addFile(src *ast.File) {
// found a BUG comment; maybe empty
if btxt := text[m[1]:]; bug_content.MatchString(btxt) {
// non-empty BUG comment; collect comment without BUG prefix
- list := copyCommentList(c.List)
+ list := append([]*ast.Comment(nil), c.List...) // make a copy
list[0].Text = text[m[1]:]
- doc.bugs = append(doc.bugs, &ast.CommentGroup{list})
+ r.bugs = append(r.bugs, (&ast.CommentGroup{list}).Text())
}
}
}
- src.Comments = nil // consumed unassociated comments - remove from ast.File node
+ src.Comments = nil // consumed unassociated comments - remove from AST
}
-// ----------------------------------------------------------------------------
-// Conversion to external representation
+func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
+ // initialize reader
+ r.filenames = make([]string, len(pkg.Files))
+ r.imports = make(map[string]int)
+ r.mode = mode
+ r.types = make(map[string]*baseType)
+ r.funcs = make(methodSet)
-func (doc *docReader) makeImports() []string {
- list := make([]string, len(doc.imports))
+ // sort package files before reading them so that the
+ // result result does not depend on map iteration order
i := 0
- for import_ := range doc.imports {
- list[i] = import_
+ for filename := range pkg.Files {
+ r.filenames[i] = filename
i++
}
- sort.Strings(list)
- return list
-}
+ sort.Strings(r.filenames)
-type sortValue []*Value
+ // process files in sorted order
+ for _, filename := range r.filenames {
+ f := pkg.Files[filename]
+ if mode&AllDecls == 0 {
+ r.fileExports(f)
+ }
+ r.readFile(f)
+ }
+}
-func (p sortValue) Len() int { return len(p) }
-func (p sortValue) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+// ----------------------------------------------------------------------------
+// Types
+
+var predeclaredTypes = map[string]bool{
+ "bool": true,
+ "byte": true,
+ "complex64": true,
+ "complex128": true,
+ "float32": true,
+ "float64": true,
+ "int": true,
+ "int8": true,
+ "int16": true,
+ "int32": true,
+ "int64": true,
+ "string": true,
+ "uint": true,
+ "uint8": true,
+ "uint16": true,
+ "uint32": true,
+ "uint64": true,
+ "uintptr": true,
+}
-func declName(d *ast.GenDecl) string {
- if len(d.Specs) != 1 {
- return ""
+func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
+ if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
+ return f // shouldn't happen, but be safe
}
- switch v := d.Specs[0].(type) {
- case *ast.ValueSpec:
- return v.Names[0].Name
- case *ast.TypeSpec:
- return v.Name.Name
+ // copy existing receiver field and set new type
+ newField := *f.Decl.Recv.List[0]
+ _, origRecvIsPtr := newField.Type.(*ast.StarExpr)
+ var typ ast.Expr = ast.NewIdent(recvTypeName)
+ if !embeddedIsPtr && origRecvIsPtr {
+ typ = &ast.StarExpr{token.NoPos, typ}
}
+ newField.Type = typ
- return ""
-}
+ // copy existing receiver field list and set new receiver field
+ newFieldList := *f.Decl.Recv
+ newFieldList.List = []*ast.Field{&newField}
-func (p sortValue) Less(i, j int) bool {
- // sort by name
- // pull blocks (name = "") up to top
- // in original order
- if ni, nj := declName(p[i].Decl), declName(p[j].Decl); ni != nj {
- return ni < nj
- }
- return p[i].order < p[j].order
+ // copy existing function declaration and set new receiver field list
+ newFuncDecl := *f.Decl
+ newFuncDecl.Recv = &newFieldList
+
+ // copy existing function documentation and set new declaration
+ newF := *f
+ newF.Decl = &newFuncDecl
+ newF.Recv = recvString(typ)
+ // the Orig field never changes
+ newF.Level = level
+
+ return &newF
}
-func specNames(specs []ast.Spec) []string {
- names := make([]string, len(specs)) // reasonable estimate
- for _, s := range specs {
- // should always be an *ast.ValueSpec, but be careful
- if s, ok := s.(*ast.ValueSpec); ok {
- for _, ident := range s.Names {
- names = append(names, ident.Name)
+// collectEmbeddedMethods collects the embedded methods from
+// all processed embedded types found in info in mset.
+//
+func collectEmbeddedMethods(mset methodSet, typ *baseType, recvTypeName string, embeddedIsPtr bool, level int) {
+ for _, e := range typ.embedded {
+ // Once an embedded type is embedded as a pointer type
+ // all embedded types in those types are treated like
+ // pointer types for the purpose of the receiver type
+ // computation; i.e., embeddedIsPtr is sticky for this
+ // embedding hierarchy.
+ thisEmbeddedIsPtr := embeddedIsPtr || e.ptr
+ for _, m := range e.typ.methods {
+ // only top-level methods are embedded
+ if m.Level == 0 {
+ mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
}
}
+ collectEmbeddedMethods(mset, e.typ, recvTypeName, thisEmbeddedIsPtr, level+1)
}
- return names
}
-func makeValues(list []*ast.GenDecl, tok token.Token) []*Value {
- d := make([]*Value, len(list)) // big enough in any case
- n := 0
- for i, decl := range list {
- if decl.Tok == tok {
- d[n] = &Value{decl.Doc.Text(), specNames(decl.Specs), decl, i}
- n++
- decl.Doc = nil // doc consumed - removed from AST
+// computeMethodSets determines the actual method sets for each type encountered.
+//
+func (r *reader) computeMethodSets() {
+ for _, t := range r.types {
+ // collect embedded methods for t
+ if t.isStruct {
+ // struct
+ collectEmbeddedMethods(t.methods, t, t.name, false, 1)
+ } else {
+ // interface
+ // TODO(gri) fix this
}
}
- d = d[0:n]
- sort.Sort(sortValue(d))
- return d
}
-type sortFunc []*Func
-
-func (p sortFunc) Len() int { return len(p) }
-func (p sortFunc) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-func (p sortFunc) Less(i, j int) bool { return p[i].Name < p[j].Name }
-
-func makeFuncs(m map[string]*ast.FuncDecl) []*Func {
- d := make([]*Func, len(m))
- i := 0
- for _, f := range m {
- doc := new(Func)
- doc.Doc = f.Doc.Text()
- f.Doc = nil // doc consumed - remove from ast.FuncDecl node
- if f.Recv != nil {
- doc.Recv = f.Recv.List[0].Type
+// cleanupTypes removes the association of functions and methods with
+// types that have no declaration. Instead, these functions and methods
+// are shown at the package level. It also removes types with missing
+// declarations or which are not visible.
+//
+func (r *reader) cleanupTypes() {
+ for _, t := range r.types {
+ visible := r.isVisible(t.name)
+ if t.decl == nil && (predeclaredTypes[t.name] || t.isEmbedded && visible) {
+ // t.name is a predeclared type (and was not redeclared in this package),
+ // or it was embedded somewhere but its declaration is missing (because
+ // the AST is incomplete): move any associated values, funcs, and methods
+ // back to the top-level so that they are not lost.
+ // 1) move values
+ r.values = append(r.values, t.values...)
+ // 2) move factory functions
+ for name, f := range t.funcs {
+ r.funcs[name] = f
+ }
+ // 3) move methods
+ for name, m := range t.methods {
+ // don't overwrite functions with the same name - drop them
+ if _, found := r.funcs[name]; !found {
+ r.funcs[name] = m
+ }
+ }
+ }
+ // remove types w/o declaration or which are not visible
+ if t.decl == nil || !visible {
+ delete(r.types, t.name)
}
- doc.Name = f.Name.Name
- doc.Decl = f
- d[i] = doc
- i++
}
- sort.Sort(sortFunc(d))
- return d
}
-type methodSet map[string]*Func
+// ----------------------------------------------------------------------------
+// Sorting
-func (mset methodSet) add(m *Func) {
- if mset[m.Name] == nil {
- mset[m.Name] = m
- }
+type data struct {
+ n int
+ swap func(i, j int)
+ less func(i, j int) bool
}
-type sortMethod []*Method
+func (d *data) Len() int { return d.n }
+func (d *data) Swap(i, j int) { d.swap(i, j) }
+func (d *data) Less(i, j int) bool { return d.less(i, j) }
-func (p sortMethod) Len() int { return len(p) }
-func (p sortMethod) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-func (p sortMethod) Less(i, j int) bool { return p[i].Func.Name < p[j].Func.Name }
+// sortBy is a helper function for sorting
+func sortBy(less func(i, j int) bool, swap func(i, j int), n int) {
+ sort.Sort(&data{n, swap, less})
+}
-func (mset methodSet) sortedList() []*Method {
- list := make([]*Method, len(mset))
+func sortedKeys(m map[string]int) []string {
+ list := make([]string, len(m))
i := 0
- for _, m := range mset {
- list[i] = &Method{Func: m}
+ for key := range m {
+ list[i] = key
i++
}
- sort.Sort(sortMethod(list))
+ sort.Strings(list)
return list
}
-type sortType []*Type
-
-func (p sortType) Len() int { return len(p) }
-func (p sortType) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-func (p sortType) Less(i, j int) bool {
- // sort by name
- // pull blocks (name = "") up to top
- // in original order
- if ni, nj := p[i].Type.Name.Name, p[j].Type.Name.Name; ni != nj {
- return ni < nj
+// sortingName returns the name to use when sorting d into place.
+//
+func sortingName(d *ast.GenDecl) string {
+ if len(d.Specs) == 1 {
+ if s, ok := d.Specs[0].(*ast.ValueSpec); ok {
+ return s.Names[0].Name
+ }
}
- return p[i].order < p[j].order
+ return ""
}
-// NOTE(rsc): This would appear not to be correct for type ( )
-// blocks, but the doc extractor above has split them into
-// individual declarations.
-func (doc *docReader) makeTypes(m map[string]*typeInfo) []*Type {
- // TODO(gri) Consider computing the embedded method information
- // before calling makeTypes. Then this function can
- // be single-phased again. Also, it might simplify some
- // of the logic.
- //
- // phase 1: associate collected declarations with Types
- list := make([]*Type, len(m))
+func sortedValues(m []*Value, tok token.Token) []*Value {
+ list := make([]*Value, len(m)) // big enough in any case
i := 0
- for _, old := range m {
- // old typeInfos may not have a declaration associated with them
- // if they are not exported but embedded, or because the package
- // is incomplete.
- if decl := old.decl; decl != nil || !old.exported() {
- // process the type even if not exported so that we have
- // its methods in case they are embedded somewhere
- t := new(Type)
- if decl != nil {
- typespec := decl.Specs[0].(*ast.TypeSpec)
- doc := typespec.Doc
- typespec.Doc = nil // doc consumed - remove from ast.TypeSpec node
- if doc == nil {
- // no doc associated with the spec, use the declaration doc, if any
- doc = decl.Doc
- }
- decl.Doc = nil // doc consumed - remove from ast.Decl node
- t.Doc = doc.Text()
- t.Type = typespec
- }
- t.Consts = makeValues(old.values, token.CONST)
- t.Vars = makeValues(old.values, token.VAR)
- t.Funcs = makeFuncs(old.factories)
- t.methods = makeFuncs(old.methods)
- // The list of embedded types' methods is computed from the list
- // of embedded types, some of which may not have been processed
- // yet (i.e., their forward link is nil) - do this in a 2nd phase.
- // The final list of methods can only be computed after that -
- // do this in a 3rd phase.
- t.Decl = old.decl
- t.order = i
- old.forward = t // old has been processed
- // only add the type to the final type list if it
- // is exported or if we want to see all types
- if old.exported() || doc.mode&AllDecls != 0 {
- list[i] = t
- i++
- }
- } else {
- // no corresponding type declaration found - move any associated
- // values, factory functions, and methods back to the top-level
- // so that they are not lost (this should only happen if a package
- // file containing the explicit type declaration is missing or if
- // an unqualified type name was used after a "." import)
- // 1) move values
- doc.values = append(doc.values, old.values...)
- // 2) move factory functions
- for name, f := range old.factories {
- doc.funcs[name] = f
- }
- // 3) move methods
- for name, f := range old.methods {
- // don't overwrite functions with the same name
- if _, found := doc.funcs[name]; !found {
- doc.funcs[name] = f
- }
- }
- }
- }
- list = list[0:i] // some types may have been ignored
-
- // phase 2: collect embedded methods for each processed typeInfo
- for _, old := range m {
- if t := old.forward; t != nil {
- // old has been processed into t; collect embedded
- // methods for t from the list of processed embedded
- // types in old (and thus for which the methods are known)
- if old.isStruct {
- // struct
- t.embedded = make(methodSet)
- collectEmbeddedMethods(t.embedded, old, old.name, false)
- } else {
- // interface
- // TODO(gri) fix this
- }
+ for _, val := range m {
+ if val.Decl.Tok == tok {
+ list[i] = val
+ i++
}
}
+ list = list[0:i]
- // phase 3: compute final method set for each Type
- for _, d := range list {
- if len(d.embedded) > 0 {
- // there are embedded methods - exclude
- // the ones with names conflicting with
- // non-embedded methods
- mset := make(methodSet)
- // top-level methods have priority
- for _, m := range d.methods {
- mset.add(m)
+ sortBy(
+ func(i, j int) bool {
+ if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj {
+ return ni < nj
}
- // add non-conflicting embedded methods
- for _, m := range d.embedded {
- mset.add(m)
- }
- d.Methods = mset.sortedList()
- } else {
- // no embedded methods - convert into a Method list
- d.Methods = make([]*Method, len(d.methods))
- for i, m := range d.methods {
- d.Methods[i] = &Method{Func: m}
- }
- }
- }
+ return list[i].order < list[j].order
+ },
+ func(i, j int) { list[i], list[j] = list[j], list[i] },
+ len(list),
+ )
- sort.Sort(sortType(list))
return list
}
-// collectEmbeddedMethods collects the embedded methods from all
-// processed embedded types found in info in mset. It considers
-// embedded types at the most shallow level first so that more
-// deeply nested embedded methods with conflicting names are
-// excluded.
-//
-func collectEmbeddedMethods(mset methodSet, info *typeInfo, recvTypeName string, embeddedIsPtr bool) {
- for _, e := range info.embedded {
- if e.typ.forward != nil { // == e was processed
- // Once an embedded type was embedded as a pointer type
- // all embedded types in those types are treated like
- // pointer types for the purpose of the receiver type
- // computation; i.e., embeddedIsPtr is sticky for this
- // embedding hierarchy.
- thisEmbeddedIsPtr := embeddedIsPtr || e.ptr
- for _, m := range e.typ.forward.methods {
- mset.add(customizeRecv(m, thisEmbeddedIsPtr, recvTypeName))
- }
- collectEmbeddedMethods(mset, e.typ, recvTypeName, thisEmbeddedIsPtr)
+func sortedTypes(m map[string]*baseType) []*Type {
+ list := make([]*Type, len(m))
+ i := 0
+ for _, t := range m {
+ list[i] = &Type{
+ Doc: t.doc,
+ Name: t.name,
+ Decl: t.decl,
+ Consts: sortedValues(t.values, token.CONST),
+ Vars: sortedValues(t.values, token.VAR),
+ Funcs: sortedFuncs(t.funcs),
+ Methods: sortedFuncs(t.methods),
}
+ i++
}
-}
-
-func customizeRecv(m *Func, embeddedIsPtr bool, recvTypeName string) *Func {
- if m == nil || m.Decl == nil || m.Decl.Recv == nil || len(m.Decl.Recv.List) != 1 {
- return m // shouldn't happen, but be safe
- }
-
- // copy existing receiver field and set new type
- newField := *m.Decl.Recv.List[0]
- _, origRecvIsPtr := newField.Type.(*ast.StarExpr)
- var typ ast.Expr = ast.NewIdent(recvTypeName)
- if !embeddedIsPtr && origRecvIsPtr {
- typ = &ast.StarExpr{token.NoPos, typ}
- }
- newField.Type = typ
- // copy existing receiver field list and set new receiver field
- newFieldList := *m.Decl.Recv
- newFieldList.List = []*ast.Field{&newField}
-
- // copy existing function declaration and set new receiver field list
- newFuncDecl := *m.Decl
- newFuncDecl.Recv = &newFieldList
-
- // copy existing function documentation and set new declaration
- newM := *m
- newM.Decl = &newFuncDecl
- newM.Recv = typ
+ sortBy(
+ func(i, j int) bool { return list[i].Name < list[j].Name },
+ func(i, j int) { list[i], list[j] = list[j], list[i] },
+ len(list),
+ )
- return &newM
+ return list
}
-func makeBugs(list []*ast.CommentGroup) []string {
- d := make([]string, len(list))
- for i, g := range list {
- d[i] = g.Text()
+func sortedFuncs(m methodSet) []*Func {
+ list := make([]*Func, len(m))
+ i := 0
+ for _, m := range m {
+ // exclude conflict entries
+ if m.Decl != nil {
+ list[i] = m
+ i++
+ }
}
- return d
-}
-
-// newDoc returns the accumulated documentation for the package.
-//
-func (doc *docReader) newDoc(importpath string, filenames []string) *Package {
- p := new(Package)
- p.Name = doc.pkgName
- p.ImportPath = importpath
- sort.Strings(filenames)
- p.Filenames = filenames
- p.Doc = doc.doc.Text()
- // makeTypes may extend the list of doc.values and
- // doc.funcs and thus must be called before any other
- // function consuming those lists
- p.Types = doc.makeTypes(doc.types)
- p.Imports = doc.makeImports()
- p.Consts = makeValues(doc.values, token.CONST)
- p.Vars = makeValues(doc.values, token.VAR)
- p.Funcs = makeFuncs(doc.funcs)
- p.Bugs = makeBugs(doc.bugs)
- return p
+ list = list[0:i]
+ sortBy(
+ func(i, j int) bool { return list[i].Name < list[j].Name },
+ func(i, j int) { list[i], list[j] = list[j], list[i] },
+ len(list),
+ )
+ return list
}
diff --git a/libgo/go/go/doc/testdata/a.out b/libgo/go/go/doc/testdata/a.0.golden
index 24db02d348f..24db02d348f 100644
--- a/libgo/go/go/doc/testdata/a.out
+++ b/libgo/go/go/doc/testdata/a.0.golden
diff --git a/libgo/go/go/doc/testdata/a.1.golden b/libgo/go/go/doc/testdata/a.1.golden
new file mode 100644
index 00000000000..24db02d348f
--- /dev/null
+++ b/libgo/go/go/doc/testdata/a.1.golden
@@ -0,0 +1,13 @@
+// comment 0 comment 1
+PACKAGE a
+
+IMPORTPATH
+ testdata/a
+
+FILENAMES
+ testdata/a0.go
+ testdata/a1.go
+
+BUGS
+ // bug0
+ // bug1
diff --git a/libgo/go/go/doc/testdata/b.out b/libgo/go/go/doc/testdata/b.0.golden
index c5ad0d0fc83..7c33300616d 100644
--- a/libgo/go/go/doc/testdata/b.out
+++ b/libgo/go/go/doc/testdata/b.0.golden
@@ -24,6 +24,12 @@ FUNCTIONS
//
func F(x int) int
+ // Always under the package functions list.
+ func NotAFactory() int
+
+ // Associated with uint type if AllDecls is set.
+ func UintFactory() uint
+
TYPES
//
@@ -32,3 +38,6 @@ TYPES
//
var V T // v
+ //
+ func (x *T) M()
+
diff --git a/libgo/go/go/doc/testdata/b.1.golden b/libgo/go/go/doc/testdata/b.1.golden
new file mode 100644
index 00000000000..f30380516bd
--- /dev/null
+++ b/libgo/go/go/doc/testdata/b.1.golden
@@ -0,0 +1,49 @@
+//
+PACKAGE b
+
+IMPORTPATH
+ testdata/b
+
+IMPORTS
+ a
+
+FILENAMES
+ testdata/b.go
+
+CONSTANTS
+ //
+ const Pi = 3.14 // Pi
+
+
+VARIABLES
+ //
+ var MaxInt int // MaxInt
+
+
+FUNCTIONS
+ //
+ func F(x int) int
+
+ // Always under the package functions list.
+ func NotAFactory() int
+
+
+TYPES
+ //
+ type T struct{} // T
+
+ //
+ var V T // v
+
+ //
+ func (x *T) M()
+
+ // Should only appear if AllDecls is set.
+ type uint struct{}
+
+ // Associated with uint type if AllDecls is set.
+ func UintFactory() uint
+
+ // Associated with uint type if AllDecls is set.
+ func uintFactory() uint
+
diff --git a/libgo/go/go/doc/testdata/b.go b/libgo/go/go/doc/testdata/b.go
index cdc77ef784c..28660f9be7c 100644
--- a/libgo/go/go/doc/testdata/b.go
+++ b/libgo/go/go/doc/testdata/b.go
@@ -6,8 +6,25 @@ package b
import "a"
+// Basic declarations
+
const Pi = 3.14 // Pi
var MaxInt int // MaxInt
type T struct{} // T
var V T // v
func F(x int) int {} // F
+func (x *T) M() {} // M
+
+// Corner cases: association with (presumed) predeclared types
+
+// Always under the package functions list.
+func NotAFactory() int {}
+
+// Associated with uint type if AllDecls is set.
+func UintFactory() uint {}
+
+// Associated with uint type if AllDecls is set.
+func uintFactory() uint {}
+
+// Should only appear if AllDecls is set.
+type uint struct{} // overrides a predeclared type uint
diff --git a/libgo/go/go/doc/testdata/c.0.golden b/libgo/go/go/doc/testdata/c.0.golden
new file mode 100644
index 00000000000..e21959b1950
--- /dev/null
+++ b/libgo/go/go/doc/testdata/c.0.golden
@@ -0,0 +1,48 @@
+//
+PACKAGE c
+
+IMPORTPATH
+ testdata/c
+
+IMPORTS
+ a
+
+FILENAMES
+ testdata/c.go
+
+TYPES
+ // A (should see this)
+ type A struct{}
+
+ // B (should see this)
+ type B struct{}
+
+ // C (should see this)
+ type C struct{}
+
+ // D (should see this)
+ type D struct{}
+
+ // E1 (should see this)
+ type E1 struct{}
+
+ // E (should see this for E2 and E3)
+ type E2 struct{}
+
+ // E (should see this for E2 and E3)
+ type E3 struct{}
+
+ // E4 (should see this)
+ type E4 struct{}
+
+ //
+ type T1 struct{}
+
+ //
+ func (t1 *T1) M()
+
+ // T2 must not show methods of local T1
+ type T2 struct {
+ a.T1 // not the same as locally declared T1
+ }
+
diff --git a/libgo/go/go/doc/testdata/c.1.golden b/libgo/go/go/doc/testdata/c.1.golden
new file mode 100644
index 00000000000..e21959b1950
--- /dev/null
+++ b/libgo/go/go/doc/testdata/c.1.golden
@@ -0,0 +1,48 @@
+//
+PACKAGE c
+
+IMPORTPATH
+ testdata/c
+
+IMPORTS
+ a
+
+FILENAMES
+ testdata/c.go
+
+TYPES
+ // A (should see this)
+ type A struct{}
+
+ // B (should see this)
+ type B struct{}
+
+ // C (should see this)
+ type C struct{}
+
+ // D (should see this)
+ type D struct{}
+
+ // E1 (should see this)
+ type E1 struct{}
+
+ // E (should see this for E2 and E3)
+ type E2 struct{}
+
+ // E (should see this for E2 and E3)
+ type E3 struct{}
+
+ // E4 (should see this)
+ type E4 struct{}
+
+ //
+ type T1 struct{}
+
+ //
+ func (t1 *T1) M()
+
+ // T2 must not show methods of local T1
+ type T2 struct {
+ a.T1 // not the same as locally declared T1
+ }
+
diff --git a/libgo/go/go/doc/testdata/c.go b/libgo/go/go/doc/testdata/c.go
new file mode 100644
index 00000000000..e0f39196dee
--- /dev/null
+++ b/libgo/go/go/doc/testdata/c.go
@@ -0,0 +1,62 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import "a"
+
+// ----------------------------------------------------------------------------
+// Test that empty declarations don't cause problems
+
+const ()
+
+type ()
+
+var ()
+
+// ----------------------------------------------------------------------------
+// Test that types with documentation on both, the Decl and the Spec node
+// are handled correctly.
+
+// A (should see this)
+type A struct{}
+
+// B (should see this)
+type (
+ B struct{}
+)
+
+type (
+ // C (should see this)
+ C struct{}
+)
+
+// D (should not see this)
+type (
+ // D (should see this)
+ D struct{}
+)
+
+// E (should see this for E2 and E3)
+type (
+ // E1 (should see this)
+ E1 struct{}
+ E2 struct{}
+ E3 struct{}
+ // E4 (should see this)
+ E4 struct{}
+)
+
+// ----------------------------------------------------------------------------
+// Test that local and imported types are different when
+// handling anonymous fields.
+
+type T1 struct{}
+
+func (t1 *T1) M() {}
+
+// T2 must not show methods of local T1
+type T2 struct {
+ a.T1 // not the same as locally declared T1
+}
diff --git a/libgo/go/go/doc/testdata/d.0.golden b/libgo/go/go/doc/testdata/d.0.golden
new file mode 100644
index 00000000000..c0051995334
--- /dev/null
+++ b/libgo/go/go/doc/testdata/d.0.golden
@@ -0,0 +1,104 @@
+//
+PACKAGE d
+
+IMPORTPATH
+ testdata/d
+
+FILENAMES
+ testdata/d1.go
+ testdata/d2.go
+
+CONSTANTS
+ // CBx constants should appear before CAx constants.
+ const (
+ CB2 = iota // before CB1
+ CB1 // before CB0
+ CB0 // at end
+ )
+
+ // CAx constants should appear after CBx constants.
+ const (
+ CA2 = iota // before CA1
+ CA1 // before CA0
+ CA0 // at end
+ )
+
+ // C0 should be first.
+ const C0 = 0
+
+ // C1 should be second.
+ const C1 = 1
+
+ // C2 should be third.
+ const C2 = 2
+
+ //
+ const (
+ // Single const declarations inside ()'s are considered ungrouped
+ // and show up in sorted order.
+ Cungrouped = 0
+ )
+
+
+VARIABLES
+ // VBx variables should appear before VAx variables.
+ var (
+ VB2 int // before VB1
+ VB1 int // before VB0
+ VB0 int // at end
+ )
+
+ // VAx variables should appear after VBx variables.
+ var (
+ VA2 int // before VA1
+ VA1 int // before VA0
+ VA0 int // at end
+ )
+
+ // V0 should be first.
+ var V0 uintptr
+
+ // V1 should be second.
+ var V1 uint
+
+ // V2 should be third.
+ var V2 int
+
+ //
+ var (
+ // Single var declarations inside ()'s are considered ungrouped
+ // and show up in sorted order.
+ Vungrouped = 0
+ )
+
+
+FUNCTIONS
+ // F0 should be first.
+ func F0()
+
+ // F1 should be second.
+ func F1()
+
+ // F2 should be third.
+ func F2()
+
+
+TYPES
+ // T0 should be first.
+ type T0 struct{}
+
+ // T1 should be second.
+ type T1 struct{}
+
+ // T2 should be third.
+ type T2 struct{}
+
+ // TG0 should be first.
+ type TG0 struct{}
+
+ // TG1 should be second.
+ type TG1 struct{}
+
+ // TG2 should be third.
+ type TG2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/d.1.golden b/libgo/go/go/doc/testdata/d.1.golden
new file mode 100644
index 00000000000..c0051995334
--- /dev/null
+++ b/libgo/go/go/doc/testdata/d.1.golden
@@ -0,0 +1,104 @@
+//
+PACKAGE d
+
+IMPORTPATH
+ testdata/d
+
+FILENAMES
+ testdata/d1.go
+ testdata/d2.go
+
+CONSTANTS
+ // CBx constants should appear before CAx constants.
+ const (
+ CB2 = iota // before CB1
+ CB1 // before CB0
+ CB0 // at end
+ )
+
+ // CAx constants should appear after CBx constants.
+ const (
+ CA2 = iota // before CA1
+ CA1 // before CA0
+ CA0 // at end
+ )
+
+ // C0 should be first.
+ const C0 = 0
+
+ // C1 should be second.
+ const C1 = 1
+
+ // C2 should be third.
+ const C2 = 2
+
+ //
+ const (
+ // Single const declarations inside ()'s are considered ungrouped
+ // and show up in sorted order.
+ Cungrouped = 0
+ )
+
+
+VARIABLES
+ // VBx variables should appear before VAx variables.
+ var (
+ VB2 int // before VB1
+ VB1 int // before VB0
+ VB0 int // at end
+ )
+
+ // VAx variables should appear after VBx variables.
+ var (
+ VA2 int // before VA1
+ VA1 int // before VA0
+ VA0 int // at end
+ )
+
+ // V0 should be first.
+ var V0 uintptr
+
+ // V1 should be second.
+ var V1 uint
+
+ // V2 should be third.
+ var V2 int
+
+ //
+ var (
+ // Single var declarations inside ()'s are considered ungrouped
+ // and show up in sorted order.
+ Vungrouped = 0
+ )
+
+
+FUNCTIONS
+ // F0 should be first.
+ func F0()
+
+ // F1 should be second.
+ func F1()
+
+ // F2 should be third.
+ func F2()
+
+
+TYPES
+ // T0 should be first.
+ type T0 struct{}
+
+ // T1 should be second.
+ type T1 struct{}
+
+ // T2 should be third.
+ type T2 struct{}
+
+ // TG0 should be first.
+ type TG0 struct{}
+
+ // TG1 should be second.
+ type TG1 struct{}
+
+ // TG2 should be third.
+ type TG2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/d1.go b/libgo/go/go/doc/testdata/d1.go
new file mode 100644
index 00000000000..ebd69419589
--- /dev/null
+++ b/libgo/go/go/doc/testdata/d1.go
@@ -0,0 +1,57 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C2 should be third.
+const C2 = 2
+
+// V2 should be third.
+var V2 int
+
+// CBx constants should appear before CAx constants.
+const (
+ CB2 = iota // before CB1
+ CB1 // before CB0
+ CB0 // at end
+)
+
+// VBx variables should appear before VAx variables.
+var (
+ VB2 int // before VB1
+ VB1 int // before VB0
+ VB0 int // at end
+)
+
+const (
+ // Single const declarations inside ()'s are considered ungrouped
+ // and show up in sorted order.
+ Cungrouped = 0
+)
+
+var (
+ // Single var declarations inside ()'s are considered ungrouped
+ // and show up in sorted order.
+ Vungrouped = 0
+)
+
+// T2 should be third.
+type T2 struct{}
+
+// Grouped types are sorted nevertheless.
+type (
+ // TG2 should be third.
+ TG2 struct{}
+
+ // TG1 should be second.
+ TG1 struct{}
+
+ // TG0 should be first.
+ TG0 struct{}
+)
+
+// F2 should be third.
+func F2() {}
diff --git a/libgo/go/go/doc/testdata/d2.go b/libgo/go/go/doc/testdata/d2.go
new file mode 100644
index 00000000000..2f56f4fa4ca
--- /dev/null
+++ b/libgo/go/go/doc/testdata/d2.go
@@ -0,0 +1,45 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C1 should be second.
+const C1 = 1
+
+// C0 should be first.
+const C0 = 0
+
+// V1 should be second.
+var V1 uint
+
+// V0 should be first.
+var V0 uintptr
+
+// CAx constants should appear after CBx constants.
+const (
+ CA2 = iota // before CA1
+ CA1 // before CA0
+ CA0 // at end
+)
+
+// VAx variables should appear after VBx variables.
+var (
+ VA2 int // before VA1
+ VA1 int // before VA0
+ VA0 int // at end
+)
+
+// T1 should be second.
+type T1 struct{}
+
+// T0 should be first.
+type T0 struct{}
+
+// F1 should be second.
+func F1() {}
+
+// F0 should be first.
+func F0() {}
diff --git a/libgo/go/go/doc/testdata/e.0.golden b/libgo/go/go/doc/testdata/e.0.golden
new file mode 100644
index 00000000000..3b128f7be8b
--- /dev/null
+++ b/libgo/go/go/doc/testdata/e.0.golden
@@ -0,0 +1,31 @@
+//
+PACKAGE e
+
+IMPORTPATH
+ testdata/e
+
+FILENAMES
+ testdata/e.go
+
+TYPES
+ // T1 has no (top-level) M method due to conflict.
+ type T1 struct {
+ // contains filtered or unexported fields
+ }
+
+ // T2 has only M as top-level method.
+ type T2 struct {
+ // contains filtered or unexported fields
+ }
+
+ // T2.M should appear as method of T2.
+ func (T2) M()
+
+ // T3 has only M as top-level method.
+ type T3 struct {
+ // contains filtered or unexported fields
+ }
+
+ // T3.M should appear as method of T3.
+ func (T3) M()
+
diff --git a/libgo/go/go/doc/testdata/e.1.golden b/libgo/go/go/doc/testdata/e.1.golden
new file mode 100644
index 00000000000..d05602d82cb
--- /dev/null
+++ b/libgo/go/go/doc/testdata/e.1.golden
@@ -0,0 +1,61 @@
+//
+PACKAGE e
+
+IMPORTPATH
+ testdata/e
+
+FILENAMES
+ testdata/e.go
+
+TYPES
+ // T1 has no (top-level) M method due to conflict.
+ type T1 struct {
+ t1
+ t2
+ }
+
+ // T2 has only M as top-level method.
+ type T2 struct {
+ t1
+ }
+
+ // T2.M should appear as method of T2.
+ func (T2) M()
+
+ // T3 has only M as top-level method.
+ type T3 struct {
+ t1e
+ t2e
+ }
+
+ // T3.M should appear as method of T3.
+ func (T3) M()
+
+ //
+ type t1 struct{}
+
+ // t1.M should not appear as method in a Tx type.
+ func (t1) M()
+
+ //
+ type t1e struct {
+ t1
+ }
+
+ // t1.M should not appear as method in a Tx type.
+ func (t1e) M()
+
+ //
+ type t2 struct{}
+
+ // t2.M should not appear as method in a Tx type.
+ func (t2) M()
+
+ //
+ type t2e struct {
+ t2
+ }
+
+ // t2.M should not appear as method in a Tx type.
+ func (t2e) M()
+
diff --git a/libgo/go/go/doc/testdata/e.go b/libgo/go/go/doc/testdata/e.go
new file mode 100644
index 00000000000..8ea6a83b66a
--- /dev/null
+++ b/libgo/go/go/doc/testdata/e.go
@@ -0,0 +1,58 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Embedding tests.
+// TODO(gri): This should be comprehensive.
+
+package e
+
+// ----------------------------------------------------------------------------
+// Conflicting methods M must not show up.
+
+type t1 struct{}
+
+// t1.M should not appear as method in a Tx type.
+func (t1) M() {}
+
+type t2 struct{}
+
+// t2.M should not appear as method in a Tx type.
+func (t2) M() {}
+
+// T1 has no (top-level) M method due to conflict.
+type T1 struct {
+ t1
+ t2
+}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level method M.
+
+// T2 has only M as top-level method.
+type T2 struct {
+ t1
+}
+
+// T2.M should appear as method of T2.
+func (T2) M() {}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level conflicting methods M.
+
+type t1e struct {
+ t1
+}
+
+type t2e struct {
+ t2
+}
+
+// T3 has only M as top-level method.
+type T3 struct {
+ t1e
+ t2e
+}
+
+// T3.M should appear as method of T3.
+func (T3) M() {}
diff --git a/libgo/go/go/doc/testdata/testing.out b/libgo/go/go/doc/testdata/testing.0.golden
index 15a90398664..15a90398664 100644
--- a/libgo/go/go/doc/testdata/testing.out
+++ b/libgo/go/go/doc/testdata/testing.0.golden
diff --git a/libgo/go/go/doc/testdata/testing.1.golden b/libgo/go/go/doc/testdata/testing.1.golden
new file mode 100644
index 00000000000..1f92f8fe3e1
--- /dev/null
+++ b/libgo/go/go/doc/testdata/testing.1.golden
@@ -0,0 +1,298 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+ testdata/testing
+
+IMPORTS
+ bytes
+ flag
+ fmt
+ io
+ os
+ runtime
+ runtime/pprof
+ strconv
+ strings
+ time
+
+FILENAMES
+ testdata/benchmark.go
+ testdata/example.go
+ testdata/testing.go
+
+VARIABLES
+ //
+ var (
+ // The short flag requests that tests run more quickly, but its functionality
+ // is provided by test writers themselves. The testing package is just its
+ // home. The all.bash installation script sets it to make installation more
+ // efficient, but by default the flag is off so a plain "gotest" will do a
+ // full test of the package.
+ short = flag.Bool("test.short", false, "run smaller test suite to save time")
+
+ // Report as tests are run; default is silent for success.
+ chatty = flag.Bool("test.v", false, "verbose: print additional output")
+ match = flag.String("test.run", "", "regular expression to select tests to run")
+ memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+ memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+ cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+ timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+ cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+ parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+
+ cpuList []int
+ )
+
+ //
+ var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+
+ //
+ var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+
+ //
+ var timer *time.Timer
+
+
+FUNCTIONS
+ // An internal function but exported because it is cross-package; ...
+ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+ // An internal function but exported because it is cross-package; ...
+ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+ //
+ func RunExamples(examples []InternalExample) (ok bool)
+
+ //
+ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+ // Short reports whether the -test.short flag is set.
+ func Short() bool
+
+ // after runs after all testing.
+ func after()
+
+ // alarm is called if the timeout expires.
+ func alarm()
+
+ // before runs before all testing.
+ func before()
+
+ // decorate inserts the final newline if needed and indentation ...
+ func decorate(s string, addFileLine bool) string
+
+ //
+ func max(x, y int) int
+
+ //
+ func min(x, y int) int
+
+ //
+ func parseCpuList()
+
+ // roundDown10 rounds a number down to the nearest power of 10.
+ func roundDown10(n int) int
+
+ // roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
+ func roundUp(n int) int
+
+ // startAlarm starts an alarm if requested.
+ func startAlarm()
+
+ // stopAlarm turns off the alarm.
+ func stopAlarm()
+
+ //
+ func tRunner(t *T, test *InternalTest)
+
+
+TYPES
+ // B is a type passed to Benchmark functions to manage benchmark ...
+ type B struct {
+ common
+ N int
+ benchmark InternalBenchmark
+ bytes int64
+ timerOn bool
+ result BenchmarkResult
+ }
+
+ // Error is equivalent to Log() followed by Fail().
+ func (c *B) Error(args ...interface{})
+
+ // Errorf is equivalent to Logf() followed by Fail().
+ func (c *B) Errorf(format string, args ...interface{})
+
+ // Fail marks the function as having failed but continues ...
+ func (c *B) Fail()
+
+ // FailNow marks the function as having failed and stops its ...
+ func (c *B) FailNow()
+
+ // Failed returns whether the function has failed.
+ func (c *B) Failed() bool
+
+ // Fatal is equivalent to Log() followed by FailNow().
+ func (c *B) Fatal(args ...interface{})
+
+ // Fatalf is equivalent to Logf() followed by FailNow().
+ func (c *B) Fatalf(format string, args ...interface{})
+
+ // Log formats its arguments using default formatting, analogous ...
+ func (c *B) Log(args ...interface{})
+
+ // Logf formats its arguments according to the format, analogous ...
+ func (c *B) Logf(format string, args ...interface{})
+
+ // ResetTimer sets the elapsed benchmark time to zero. It does not ...
+ func (b *B) ResetTimer()
+
+ // SetBytes records the number of bytes processed in a single ...
+ func (b *B) SetBytes(n int64)
+
+ // StartTimer starts timing a test. This function is called ...
+ func (b *B) StartTimer()
+
+ // StopTimer stops timing a test. This can be used to pause the ...
+ func (b *B) StopTimer()
+
+ // launch launches the benchmark function. It gradually increases ...
+ func (b *B) launch()
+
+ // log generates the output. It's always at the same stack depth.
+ func (c *B) log(s string)
+
+ //
+ func (b *B) nsPerOp() int64
+
+ // run times the benchmark function in a separate goroutine.
+ func (b *B) run() BenchmarkResult
+
+ // runN runs a single benchmark for the specified number of ...
+ func (b *B) runN(n int)
+
+ // trimOutput shortens the output from a benchmark, which can be ...
+ func (b *B) trimOutput()
+
+ // The results of a benchmark run.
+ type BenchmarkResult struct {
+ N int // The number of iterations.
+ T time.Duration // The total time taken.
+ Bytes int64 // Bytes processed in one iteration.
+ }
+
+ // Benchmark benchmarks a single function. Useful for creating ...
+ func Benchmark(f func(b *B)) BenchmarkResult
+
+ //
+ func (r BenchmarkResult) NsPerOp() int64
+
+ //
+ func (r BenchmarkResult) String() string
+
+ //
+ func (r BenchmarkResult) mbPerSec() float64
+
+ // An internal type but exported because it is cross-package; part ...
+ type InternalBenchmark struct {
+ Name string
+ F func(b *B)
+ }
+
+ //
+ type InternalExample struct {
+ Name string
+ F func()
+ Output string
+ }
+
+ // An internal type but exported because it is cross-package; part ...
+ type InternalTest struct {
+ Name string
+ F func(*T)
+ }
+
+ // T is a type passed to Test functions to manage test state and ...
+ type T struct {
+ common
+ name string // Name of test.
+ startParallel chan bool // Parallel tests will wait on this.
+ }
+
+ // Error is equivalent to Log() followed by Fail().
+ func (c *T) Error(args ...interface{})
+
+ // Errorf is equivalent to Logf() followed by Fail().
+ func (c *T) Errorf(format string, args ...interface{})
+
+ // Fail marks the function as having failed but continues ...
+ func (c *T) Fail()
+
+ // FailNow marks the function as having failed and stops its ...
+ func (c *T) FailNow()
+
+ // Failed returns whether the function has failed.
+ func (c *T) Failed() bool
+
+ // Fatal is equivalent to Log() followed by FailNow().
+ func (c *T) Fatal(args ...interface{})
+
+ // Fatalf is equivalent to Logf() followed by FailNow().
+ func (c *T) Fatalf(format string, args ...interface{})
+
+ // Log formats its arguments using default formatting, analogous ...
+ func (c *T) Log(args ...interface{})
+
+ // Logf formats its arguments according to the format, analogous ...
+ func (c *T) Logf(format string, args ...interface{})
+
+ // Parallel signals that this test is to be run in parallel with ...
+ func (t *T) Parallel()
+
+ // log generates the output. It's always at the same stack depth.
+ func (c *T) log(s string)
+
+ //
+ func (t *T) report()
+
+ // common holds the elements common between T and B and captures ...
+ type common struct {
+ output []byte // Output generated by test or benchmark.
+ failed bool // Test or benchmark has failed.
+ start time.Time // Time test or benchmark started
+ duration time.Duration
+ self interface{} // To be sent on signal channel when done.
+ signal chan interface{} // Output for serial tests.
+ }
+
+ // Error is equivalent to Log() followed by Fail().
+ func (c *common) Error(args ...interface{})
+
+ // Errorf is equivalent to Logf() followed by Fail().
+ func (c *common) Errorf(format string, args ...interface{})
+
+ // Fail marks the function as having failed but continues ...
+ func (c *common) Fail()
+
+ // FailNow marks the function as having failed and stops its ...
+ func (c *common) FailNow()
+
+ // Failed returns whether the function has failed.
+ func (c *common) Failed() bool
+
+ // Fatal is equivalent to Log() followed by FailNow().
+ func (c *common) Fatal(args ...interface{})
+
+ // Fatalf is equivalent to Logf() followed by FailNow().
+ func (c *common) Fatalf(format string, args ...interface{})
+
+ // Log formats its arguments using default formatting, analogous ...
+ func (c *common) Log(args ...interface{})
+
+ // Logf formats its arguments according to the format, analogous ...
+ func (c *common) Logf(format string, args ...interface{})
+
+ // log generates the output. It's always at the same stack depth.
+ func (c *common) log(s string)
+
diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go
index 4b72f38518e..f1b4ce34d1a 100644
--- a/libgo/go/go/parser/interface.go
+++ b/libgo/go/go/parser/interface.go
@@ -45,12 +45,14 @@ func readSource(filename string, src interface{}) ([]byte, error) {
return ioutil.ReadFile(filename)
}
-// The mode parameter to the Parse* functions is a set of flags (or 0).
+// A Mode value is a set of flags (or 0).
// They control the amount of source code parsed and other optional
// parser functionality.
//
+type Mode uint
+
const (
- PackageClauseOnly uint = 1 << iota // parsing stops after package clause
+ PackageClauseOnly Mode = 1 << iota // parsing stops after package clause
ImportsOnly // parsing stops after import declarations
ParseComments // parse comments and add them to AST
Trace // print a trace of parsed productions
@@ -77,7 +79,7 @@ const (
// representing the fragments of erroneous source code). Multiple errors
// are returned via a scanner.ErrorList which is sorted by file position.
//
-func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint) (*ast.File, error) {
+func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (*ast.File, error) {
text, err := readSource(filename, src)
if err != nil {
return nil, err
@@ -97,7 +99,7 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint)
// returned. If a parse error occurred, a non-nil but incomplete map and the
// first error encountered are returned.
//
-func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode uint) (pkgs map[string]*ast.Package, first error) {
+func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) {
fd, err := os.Open(path)
if err != nil {
return nil, err
@@ -117,7 +119,10 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
name := src.Name.Name
pkg, found := pkgs[name]
if !found {
- pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
+ pkg = &ast.Package{
+ Name: name,
+ Files: make(map[string]*ast.File),
+ }
pkgs[name] = pkg
}
pkg.Files[filename] = src
diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go
index d90f5775df4..6bee8de9f65 100644
--- a/libgo/go/go/parser/parser.go
+++ b/libgo/go/go/parser/parser.go
@@ -23,7 +23,7 @@ type parser struct {
scanner scanner.Scanner
// Tracing/debugging
- mode uint // parsing mode
+ mode Mode // parsing mode
trace bool // == (mode & Trace != 0)
indent uint // indentation used for tracing output
@@ -52,9 +52,9 @@ type parser struct {
targetStack [][]*ast.Ident // stack of unresolved labels
}
-func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
p.file = fset.AddFile(filename, fset.Base(), len(src))
- var m uint
+ var m scanner.Mode
if mode&ParseComments != 0 {
m = scanner.ScanComments
}
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index 6817cc42add..5f3b4d4a740 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -72,7 +72,7 @@ func (p *printer) setComment(g *ast.CommentGroup) {
// for some reason there are pending comments; this
// should never happen - handle gracefully and flush
// all comments up to g, ignore anything after that
- p.flush(p.fset.Position(g.List[0].Pos()), token.ILLEGAL)
+ p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
}
p.comments[0] = g
p.cindex = 0
@@ -122,10 +122,10 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
p.print(blank)
}
- prev := p.fset.Position(prev0)
- next := p.fset.Position(next0)
- line := p.fset.Position(list[0].Pos()).Line
- endLine := p.fset.Position(list[len(list)-1].End()).Line
+ prev := p.posFor(prev0)
+ next := p.posFor(next0)
+ line := p.lineFor(list[0].Pos())
+ endLine := p.lineFor(list[len(list)-1].End())
if prev.IsValid() && prev.Line == line && line == endLine {
// all list entries on a single line
@@ -169,7 +169,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
// print all list elements
for i, x := range list {
prevLine := line
- line = p.fset.Position(x.Pos()).Line
+ line = p.lineFor(x.Pos())
// determine if the next linebreak, if any, needs to use formfeed:
// in general, use the entire node size to make the decision; for
@@ -272,23 +272,32 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.print(fields.Opening, token.LPAREN)
if len(fields.List) > 0 {
+ prevLine := p.lineFor(fields.Opening)
ws := indent
- var prevLine, line int
for i, par := range fields.List {
+ // determine par begin and end line (may be different
+ // if there are multiple parameter names for this par
+ // or the type is on a separate line)
+ var parLineBeg int
+ var parLineEnd = p.lineFor(par.Type.Pos())
+ if len(par.Names) > 0 {
+ parLineBeg = p.lineFor(par.Names[0].Pos())
+ } else {
+ parLineBeg = parLineEnd
+ }
+ // separating "," if needed
if i > 0 {
p.print(token.COMMA)
- if len(par.Names) > 0 {
- line = p.fset.Position(par.Names[0].Pos()).Line
- } else {
- line = p.fset.Position(par.Type.Pos()).Line
- }
- if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ws, true) {
- ws = ignore
- *multiLine = true
- } else {
- p.print(blank)
- }
}
+ // separator if needed (linebreak or blank)
+ if 0 < prevLine && prevLine < parLineBeg && p.linebreak(parLineBeg, 0, ws, true) {
+ // break line if the opening "(" or previous parameter ended on a different line
+ ws = ignore
+ *multiLine = true
+ } else if i > 0 {
+ p.print(blank)
+ }
+ // parameter names
if len(par.Names) > 0 {
// Very subtle: If we indented before (ws == ignore), identList
// won't indent again. If we didn't (ws == indent), identList will
@@ -299,11 +308,18 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.identList(par.Names, ws == indent, multiLine)
p.print(blank)
}
+ // parameter type
p.expr(par.Type, multiLine)
- prevLine = p.fset.Position(par.Type.Pos()).Line
+ prevLine = parLineEnd
}
+ // if the closing ")" is on a separate line from the last parameter,
+ // print an additional "," and line break
+ if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
+ p.print(",")
+ p.linebreak(closing, 0, ignore, true)
+ }
+ // unindent if we indented
if ws == ignore {
- // unindent if we indented
p.print(unindent)
}
}
@@ -364,8 +380,8 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
lbrace := fields.Opening
list := fields.List
rbrace := fields.Closing
- hasComments := isIncomplete || p.commentBefore(p.fset.Position(rbrace))
- srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.fset.Position(lbrace).Line == p.fset.Position(rbrace).Line
+ hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace))
+ srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace)
if !hasComments && srcIsOneLine {
// possibly a one-line struct/interface
@@ -408,7 +424,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
var ml bool
for i, f := range list {
if i > 0 {
- p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
+ p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml)
}
ml = false
extraTabs := 0
@@ -443,7 +459,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
if len(list) > 0 {
p.print(formfeed)
}
- p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+ p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
p.setLineComment("// contains filtered or unexported fields")
}
@@ -452,7 +468,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
var ml bool
for i, f := range list {
if i > 0 {
- p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
+ p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml)
}
ml = false
p.setComment(f.Doc)
@@ -470,7 +486,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
if len(list) > 0 {
p.print(formfeed)
}
- p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+ p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
p.setLineComment("// contains filtered or unexported methods")
}
@@ -626,7 +642,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
p.print(blank)
}
xline := p.pos.Line // before the operator (it may be on the next line!)
- yline := p.fset.Position(x.Y.Pos()).Line
+ yline := p.lineFor(x.Y.Pos())
p.print(x.OpPos, x.Op)
if xline != yline && xline > 0 && yline > 0 {
// at least one line break, but respect an extra empty line
@@ -919,7 +935,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
for i, s := range list {
// _indent == 0 only for lists of switch/select case clauses;
// in those cases each clause is a new section
- p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, i == 0 || _indent == 0 || multiLine)
+ p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine)
multiLine = false
p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
}
@@ -932,7 +948,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
func (p *printer) block(s *ast.BlockStmt, indent int) {
p.print(s.Pos(), token.LBRACE)
p.stmtList(s.List, indent, true)
- p.linebreak(p.fset.Position(s.Rbrace).Line, 1, ignore, true)
+ p.linebreak(p.lineFor(s.Rbrace), 1, ignore, true)
p.print(s.Rbrace, token.RBRACE)
}
@@ -1033,7 +1049,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
break
}
} else {
- p.linebreak(p.fset.Position(s.Stmt.Pos()).Line, 1, ignore, true)
+ p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
}
p.stmt(s.Stmt, nextIsRBrace, multiLine)
@@ -1145,7 +1161,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
case *ast.SelectStmt:
p.print(token.SELECT, blank)
body := s.Body
- if len(body.List) == 0 && !p.commentBefore(p.fset.Position(body.Rbrace)) {
+ if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) {
// print empty select statement w/o comments on one line
p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE)
} else {
@@ -1337,7 +1353,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
var ml bool
for i, s := range d.Specs {
if i > 0 {
- p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
+ p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml)
}
ml = false
p.valueSpec(s.(*ast.ValueSpec), keepType[i], false, &ml)
@@ -1346,7 +1362,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
var ml bool
for i, s := range d.Specs {
if i > 0 {
- p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
+ p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml)
}
ml = false
p.spec(s, n, false, &ml)
@@ -1403,11 +1419,11 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
pos1 := b.Pos()
pos2 := b.Rbrace
- if pos1.IsValid() && pos2.IsValid() && p.fset.Position(pos1).Line != p.fset.Position(pos2).Line {
+ if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
// opening and closing brace are on different lines - don't make it a one-liner
return false
}
- if len(b.List) > 5 || p.commentBefore(p.fset.Position(pos2)) {
+ if len(b.List) > 5 || p.commentBefore(p.posFor(pos2)) {
// too many statements or there is a comment inside - don't make it a one-liner
return false
}
@@ -1458,7 +1474,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
// are on the same line; if they are on different lines (or unknown)
// the result is infinity.
func (p *printer) distance(from0 token.Pos, to token.Position) int {
- from := p.fset.Position(from0)
+ from := p.posFor(from0)
if from.IsValid() && to.IsValid() && from.Line == to.Line {
return to.Column - from.Column
}
@@ -1527,7 +1543,7 @@ func (p *printer) file(src *ast.File) {
if prev != tok || getDoc(d) != nil {
min = 2
}
- p.linebreak(p.fset.Position(d.Pos()).Line, min, ignore, false)
+ p.linebreak(p.lineFor(d.Pos()), min, ignore, false)
p.decl(d, ignoreMultiLine)
}
}
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index c720f2e665c..52dfff6f4b3 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -75,6 +75,10 @@ type printer struct {
// Cache of already computed node sizes.
nodeSizes map[ast.Node]int
+
+ // Cache of most recently computed line position.
+ cachedPos token.Pos
+ cachedLine int // line corresponding to cachedPos
}
func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]int) {
@@ -82,6 +86,7 @@ func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]
p.fset = fset
p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short
p.nodeSizes = nodeSizes
+ p.cachedPos = -1
}
func (p *printer) internalError(msg ...interface{}) {
@@ -92,6 +97,19 @@ func (p *printer) internalError(msg ...interface{}) {
}
}
+func (p *printer) posFor(pos token.Pos) token.Position {
+ // not used frequently enough to cache entire token.Position
+ return p.fset.Position(pos)
+}
+
+func (p *printer) lineFor(pos token.Pos) int {
+ if pos != p.cachedPos {
+ p.cachedPos = pos
+ p.cachedLine = p.fset.Position(pos).Line
+ }
+ return p.cachedLine
+}
+
// writeByte writes ch to p.output and updates p.pos.
func (p *printer) writeByte(ch byte) {
p.output.WriteByte(ch)
@@ -529,7 +547,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
// shortcut common case of //-style comments
if text[1] == '/' {
- p.writeItem(p.fset.Position(comment.Pos()), text, true)
+ p.writeItem(p.posFor(comment.Pos()), text, true)
return
}
@@ -540,7 +558,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
// write comment lines, separated by formfeed,
// without a line break after the last line
- pos := p.fset.Position(comment.Pos())
+ pos := p.posFor(comment.Pos())
for i, line := range lines {
if i > 0 {
p.writeByte('\f')
@@ -602,14 +620,14 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro
var last *ast.Comment
for ; p.commentBefore(next); p.cindex++ {
for _, c := range p.comments[p.cindex].List {
- p.writeCommentPrefix(p.fset.Position(c.Pos()), next, last, c, tok.IsKeyword())
+ p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok.IsKeyword())
p.writeComment(c)
last = c
}
}
if last != nil {
- if last.Text[1] == '*' && p.fset.Position(last.Pos()).Line == next.Line {
+ if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line {
// the last comment is a /*-style comment and the next item
// follows on the same line: separate with an extra blank
p.writeByte(' ')
@@ -770,7 +788,7 @@ func (p *printer) print(args ...interface{}) {
tok = x
case token.Pos:
if x.IsValid() {
- next = p.fset.Position(x) // accurate position of next item
+ next = p.posFor(x) // accurate position of next item
}
tok = p.lastTok
case string:
@@ -813,7 +831,7 @@ func (p *printer) print(args ...interface{}) {
// before the next position in the source code.
//
func (p *printer) commentBefore(next token.Position) bool {
- return p.cindex < len(p.comments) && p.fset.Position(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
+ return p.cindex < len(p.comments) && p.posFor(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
}
// Flush prints any pending comments and whitespace occurring textually
diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden
index 239ba890304..928b8ce0a9f 100644
--- a/libgo/go/go/printer/testdata/declarations.golden
+++ b/libgo/go/go/printer/testdata/declarations.golden
@@ -773,30 +773,39 @@ func ManageStatus(in <-chan *Status, req <-chan Request,
TargetHistorySize int) {
}
-func MultiLineSignature0(a, b, c int) {
+func MultiLineSignature0(
+ a, b, c int,
+) {
}
-func MultiLineSignature1(a, b, c int,
- u, v, w float) {
+func MultiLineSignature1(
+ a, b, c int,
+ u, v, w float,
+) {
}
-func MultiLineSignature2(a, b,
- c int) {
+func MultiLineSignature2(
+ a, b,
+ c int,
+) {
}
-func MultiLineSignature3(a, b,
+func MultiLineSignature3(
+ a, b,
c int, u, v,
w float,
x ...int) {
}
-func MultiLineSignature4(a, b, c int,
+func MultiLineSignature4(
+ a, b, c int,
u, v,
w float,
x ...int) {
}
-func MultiLineSignature5(a, b, c int,
+func MultiLineSignature5(
+ a, b, c int,
u, v, w float,
p, q,
r string,
@@ -805,25 +814,34 @@ func MultiLineSignature5(a, b, c int,
// make sure it also works for methods in interfaces
type _ interface {
- MultiLineSignature0(a, b, c int)
+ MultiLineSignature0(
+ a, b, c int,
+ )
- MultiLineSignature1(a, b, c int,
- u, v, w float)
+ MultiLineSignature1(
+ a, b, c int,
+ u, v, w float,
+ )
- MultiLineSignature2(a, b,
- c int)
+ MultiLineSignature2(
+ a, b,
+ c int,
+ )
- MultiLineSignature3(a, b,
+ MultiLineSignature3(
+ a, b,
c int, u, v,
w float,
x ...int)
- MultiLineSignature4(a, b, c int,
+ MultiLineSignature4(
+ a, b, c int,
u, v,
w float,
x ...int)
- MultiLineSignature5(a, b, c int,
+ MultiLineSignature5(
+ a, b, c int,
u, v, w float,
p, q,
r string,
diff --git a/libgo/go/go/printer/testdata/linebreaks.golden b/libgo/go/go/printer/testdata/linebreaks.golden
index be780da677a..006cf171848 100644
--- a/libgo/go/go/printer/testdata/linebreaks.golden
+++ b/libgo/go/go/printer/testdata/linebreaks.golden
@@ -220,4 +220,56 @@ testLoop:
}
}
+// Respect line breaks in function calls.
+func _() {
+ f(x)
+ f(x,
+ x)
+ f(x,
+ x,
+ )
+ f(
+ x,
+ x)
+ f(
+ x,
+ x,
+ )
+}
+
+// Respect line breaks in function declarations.
+func _(x T) {}
+func _(x T,
+ y T) {
+}
+func _(x T,
+ y T,
+) {
+}
+func _(
+ x T,
+ y T) {
+}
+func _(
+ x T,
+ y T,
+) {
+}
+
+// Example from issue 2597.
+func ManageStatus0(
+ in <-chan *Status,
+ req <-chan Request,
+ stat chan<- *TargetInfo,
+ TargetHistorySize int) {
+}
+
+func ManageStatus1(
+ in <-chan *Status,
+ req <-chan Request,
+ stat chan<- *TargetInfo,
+ TargetHistorySize int,
+) {
+}
+
// There should be exactly one linebreak after this comment.
diff --git a/libgo/go/go/printer/testdata/linebreaks.input b/libgo/go/go/printer/testdata/linebreaks.input
index 457b491e6d2..e782bb04443 100644
--- a/libgo/go/go/printer/testdata/linebreaks.input
+++ b/libgo/go/go/printer/testdata/linebreaks.input
@@ -220,4 +220,52 @@ testLoop:
}
}
+// Respect line breaks in function calls.
+func _() {
+ f(x)
+ f(x,
+ x)
+ f(x,
+ x,
+ )
+ f(
+ x,
+ x)
+ f(
+ x,
+ x,
+ )
+}
+
+// Respect line breaks in function declarations.
+func _(x T) {}
+func _(x T,
+ y T) {}
+func _(x T,
+ y T,
+) {}
+func _(
+ x T,
+ y T) {}
+func _(
+ x T,
+ y T,
+) {}
+
+// Example from issue 2597.
+func ManageStatus0(
+ in <-chan *Status,
+ req <-chan Request,
+ stat chan<- *TargetInfo,
+ TargetHistorySize int) {
+}
+
+func ManageStatus1(
+ in <-chan *Status,
+ req <-chan Request,
+ stat chan<- *TargetInfo,
+ TargetHistorySize int,
+) {
+}
+
// There should be exactly one linebreak after this comment.
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index 05665b25487..7c72c0a46b9 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -40,7 +40,7 @@ type Scanner struct {
dir string // directory portion of file.Name()
src []byte // source
err ErrorHandler // error reporting; or nil
- mode uint // scanning mode
+ mode Mode // scanning mode
// scanning state
ch rune // current character
@@ -86,12 +86,14 @@ func (S *Scanner) next() {
}
}
-// The mode parameter to the Init function is a set of flags (or 0).
+// A mode value is set of flags (or 0).
// They control scanner behavior.
//
+type Mode uint
+
const (
- ScanComments = 1 << iota // return comments as COMMENT tokens
- dontInsertSemis // do not automatically insert semicolons - for testing only
+ ScanComments Mode = 1 << iota // return comments as COMMENT tokens
+ dontInsertSemis // do not automatically insert semicolons - for testing only
)
// Init prepares the scanner S to tokenize the text src by setting the
@@ -109,7 +111,7 @@ const (
// Note that Init may call err if there is an error in the first character
// of the file.
//
-func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint) {
+func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) {
// Explicitly initialize all fields since a scanner may be reused.
if file.Size() != len(src) {
panic("file size does not match src len")
diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go
index 2e4dd4fff63..af45bc5b1c8 100644
--- a/libgo/go/go/scanner/scanner_test.go
+++ b/libgo/go/go/scanner/scanner_test.go
@@ -281,7 +281,7 @@ func TestScan(t *testing.T) {
}
}
-func checkSemi(t *testing.T, line string, mode uint) {
+func checkSemi(t *testing.T, line string, mode Mode) {
var S Scanner
file := fset.AddFile("TestSemis", fset.Base(), len(line))
S.Init(file, []byte(line), nil, mode)
diff --git a/libgo/go/html/escape.go b/libgo/go/html/escape.go
index 42be865ef08..c0b5262af83 100644
--- a/libgo/go/html/escape.go
+++ b/libgo/go/html/escape.go
@@ -10,6 +10,10 @@ import (
"unicode/utf8"
)
+type writer interface {
+ WriteString(string) (int, error)
+}
+
// These replacements permit compatibility with old numeric entities that
// assumed Windows-1252 encoding.
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go
index 65f4b3ac2e5..cbe1a5839df 100644
--- a/libgo/go/io/ioutil/ioutil.go
+++ b/libgo/go/io/ioutil/ioutil.go
@@ -14,9 +14,22 @@ import (
// readAll reads from r until an error or EOF and returns the data it read
// from the internal buffer allocated with a specified capacity.
-func readAll(r io.Reader, capacity int64) ([]byte, error) {
+func readAll(r io.Reader, capacity int64) (b []byte, err error) {
buf := bytes.NewBuffer(make([]byte, 0, capacity))
- _, err := buf.ReadFrom(r)
+ // If the buffer overflows, we will get bytes.ErrTooLarge.
+ // Return that as an error. Any other panic remains.
+ defer func() {
+ e := recover()
+ if e == nil {
+ return
+ }
+ if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
+ err = panicErr
+ } else {
+ panic(e)
+ }
+ }()
+ _, err = buf.ReadFrom(r)
return buf.Bytes(), err
}
diff --git a/libgo/go/math/big/arith.go b/libgo/go/math/big/arith.go
index 242bd1e8cc4..41de17ba416 100644
--- a/libgo/go/math/big/arith.go
+++ b/libgo/go/math/big/arith.go
@@ -54,6 +54,7 @@ func subWW_g(x, y, c Word) (z1, z0 Word) {
// z1<<_W + z0 = x*y
func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) }
+
// Adapted from Warren, Hacker's Delight, p. 132.
func mulWW_g(x, y Word) (z1, z0 Word) {
x0 := x & _M2
@@ -80,11 +81,24 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
}
// Length of x in bits.
-func bitLen(x Word) (n int) {
- for ; x >= 0x100; x >>= 8 {
+func bitLen(x Word) (n int) { return bitLen_g(x) }
+func bitLen_g(x Word) (n int) {
+ for ; x >= 0x8000; x >>= 16 {
+ n += 16
+ }
+ if x >= 0x80 {
+ x >>= 8
n += 8
}
- for ; x > 0; x >>= 1 {
+ if x >= 0x8 {
+ x >>= 4
+ n += 4
+ }
+ if x >= 0x2 {
+ x >>= 2
+ n += 2
+ }
+ if x >= 0x1 {
n++
}
return
@@ -104,6 +118,7 @@ func leadingZeros(x Word) uint {
// q = (u1<<_W + u0 - r)/y
func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) }
+
// Adapted from Warren, Hacker's Delight, p. 152.
func divWW_g(u1, u0, v Word) (q, r Word) {
if u1 >= v {
diff --git a/libgo/go/math/big/arith_decl.go b/libgo/go/math/big/arith_decl.go
index 95fcd8b94be..068cc8d9388 100644
--- a/libgo/go/math/big/arith_decl.go
+++ b/libgo/go/math/big/arith_decl.go
@@ -16,3 +16,4 @@ func shrVU(z, x []Word, s uint) (c Word)
func mulAddVWW(z, x []Word, y, r Word) (c Word)
func addMulVVW(z, x []Word, y Word) (c Word)
func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
+func bitLen(x Word) (n int)
diff --git a/libgo/go/math/big/arith_test.go b/libgo/go/math/big/arith_test.go
index b6c56c39ef4..c7e3d284c2d 100644
--- a/libgo/go/math/big/arith_test.go
+++ b/libgo/go/math/big/arith_test.go
@@ -333,3 +333,40 @@ func TestMulAddWWW(t *testing.T) {
}
}
}
+
+func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
+ for i := 0; i <= _W; i++ {
+ x := Word(1) << uint(i-1) // i == 0 => x == 0
+ n := f(x)
+ if n != i {
+ t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
+ }
+ }
+}
+
+func TestWordBitLen(t *testing.T) {
+ testWordBitLen(t, "bitLen", bitLen)
+ testWordBitLen(t, "bitLen_g", bitLen_g)
+}
+
+// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
+func benchmarkBitLenN(b *testing.B, nbits uint) {
+ testword := Word((uint64(1) << nbits) - 1)
+ for i := 0; i < b.N; i++ {
+ bitLen(testword)
+ }
+}
+
+// Individual bitLen tests. Numbers chosen to examine both sides
+// of powers-of-two boundaries.
+func BenchmarkBitLen0(b *testing.B) { benchmarkBitLenN(b, 0) }
+func BenchmarkBitLen1(b *testing.B) { benchmarkBitLenN(b, 1) }
+func BenchmarkBitLen2(b *testing.B) { benchmarkBitLenN(b, 2) }
+func BenchmarkBitLen3(b *testing.B) { benchmarkBitLenN(b, 3) }
+func BenchmarkBitLen4(b *testing.B) { benchmarkBitLenN(b, 4) }
+func BenchmarkBitLen5(b *testing.B) { benchmarkBitLenN(b, 5) }
+func BenchmarkBitLen8(b *testing.B) { benchmarkBitLenN(b, 8) }
+func BenchmarkBitLen9(b *testing.B) { benchmarkBitLenN(b, 9) }
+func BenchmarkBitLen16(b *testing.B) { benchmarkBitLenN(b, 16) }
+func BenchmarkBitLen17(b *testing.B) { benchmarkBitLenN(b, 17) }
+func BenchmarkBitLen31(b *testing.B) { benchmarkBitLenN(b, 31) }
diff --git a/libgo/go/net/cgo_stub.go b/libgo/go/net/cgo_stub.go
index 66aff837d0a..52e57d7400e 100644
--- a/libgo/go/net/cgo_stub.go
+++ b/libgo/go/net/cgo_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nocgo
+// +build !cgo
// Stub cgo routines for systems that do not use cgo to do network lookups.
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 00acb8477d2..5d596bcb6b4 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -8,24 +8,59 @@ import (
"time"
)
-func resolveNetAddr(op, net, addr string) (a Addr, err error) {
- if addr == "" {
- return nil, &OpError{op, net, nil, errMissingAddress}
+func parseDialNetwork(net string) (afnet string, proto int, err error) {
+ i := last(net, ':')
+ if i < 0 { // no colon
+ switch net {
+ case "tcp", "tcp4", "tcp6":
+ case "udp", "udp4", "udp6":
+ case "unix", "unixgram", "unixpacket":
+ default:
+ return "", 0, UnknownNetworkError(net)
+ }
+ return net, 0, nil
}
- switch net {
- case "tcp", "tcp4", "tcp6":
- a, err = ResolveTCPAddr(net, addr)
- case "udp", "udp4", "udp6":
- a, err = ResolveUDPAddr(net, addr)
- case "unix", "unixgram", "unixpacket":
- a, err = ResolveUnixAddr(net, addr)
+ afnet = net[:i]
+ switch afnet {
case "ip", "ip4", "ip6":
- a, err = ResolveIPAddr(net, addr)
- default:
- err = UnknownNetworkError(net)
+ protostr := net[i+1:]
+ proto, i, ok := dtoi(protostr, 0)
+ if !ok || i != len(protostr) {
+ proto, err = lookupProtocol(protostr)
+ if err != nil {
+ return "", 0, err
+ }
+ }
+ return afnet, proto, nil
}
+ return "", 0, UnknownNetworkError(net)
+}
+
+func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
+ afnet, _, err = parseDialNetwork(net)
if err != nil {
- return nil, &OpError{op, net + " " + addr, nil, err}
+ return "", nil, &OpError{op, net, nil, err}
+ }
+ if op == "dial" && addr == "" {
+ return "", nil, &OpError{op, net, nil, errMissingAddress}
+ }
+ switch afnet {
+ case "tcp", "tcp4", "tcp6":
+ if addr != "" {
+ a, err = ResolveTCPAddr(afnet, addr)
+ }
+ case "udp", "udp4", "udp6":
+ if addr != "" {
+ a, err = ResolveUDPAddr(afnet, addr)
+ }
+ case "ip", "ip4", "ip6":
+ if addr != "" {
+ a, err = ResolveIPAddr(afnet, addr)
+ }
+ case "unix", "unixgram", "unixpacket":
+ if addr != "" {
+ a, err = ResolveUnixAddr(afnet, addr)
+ }
}
return
}
@@ -34,20 +69,27 @@ func resolveNetAddr(op, net, addr string) (a Addr, err error) {
//
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
-// (IPv4-only), "ip6" (IPv6-only), "unix" and "unixgram".
+// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket".
//
-// For IP networks, addresses have the form host:port. If host is
-// a literal IPv6 address, it must be enclosed in square brackets.
-// The functions JoinHostPort and SplitHostPort manipulate
-// addresses in this form.
+// For TCP and UDP networks, addresses have the form host:port.
+// If host is a literal IPv6 address, it must be enclosed
+// in square brackets. The functions JoinHostPort and SplitHostPort
+// manipulate addresses in this form.
//
// Examples:
// Dial("tcp", "12.34.56.78:80")
// Dial("tcp", "google.com:80")
// Dial("tcp", "[de:ad:be:ef::ca:fe]:80")
//
+// For IP networks, addr must be "ip", "ip4" or "ip6" followed
+// by a colon and a protocol number or name.
+//
+// Examples:
+// Dial("ip4:1", "127.0.0.1")
+// Dial("ip6:ospf", "::1")
+//
func Dial(net, addr string) (Conn, error) {
- addri, err := resolveNetAddr("dial", net, addr)
+ _, addri, err := resolveNetAddr("dial", net, addr)
if err != nil {
return nil, err
}
@@ -60,10 +102,10 @@ func dialAddr(net, addr string, addri Addr) (c Conn, err error) {
c, err = DialTCP(net, nil, ra)
case *UDPAddr:
c, err = DialUDP(net, nil, ra)
- case *UnixAddr:
- c, err = DialUnix(net, nil, ra)
case *IPAddr:
c, err = DialIP(net, nil, ra)
+ case *UnixAddr:
+ c, err = DialUnix(net, nil, ra)
default:
err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkError(net)}
}
@@ -89,7 +131,7 @@ func DialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
ch := make(chan pair, 1)
resolvedAddr := make(chan Addr, 1)
go func() {
- addri, err := resolveNetAddr("dial", net, addr)
+ _, addri, err := resolveNetAddr("dial", net, addr)
if err != nil {
ch <- pair{nil, err}
return
@@ -130,86 +172,57 @@ func (a stringAddr) Network() string { return a.net }
func (a stringAddr) String() string { return a.addr }
// Listen announces on the local network address laddr.
-// The network string net must be a stream-oriented
-// network: "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
-func Listen(net, laddr string) (l Listener, err error) {
- switch net {
+// The network string net must be a stream-oriented network:
+// "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
+func Listen(net, laddr string) (Listener, error) {
+ afnet, a, err := resolveNetAddr("listen", net, laddr)
+ if err != nil {
+ return nil, err
+ }
+ switch afnet {
case "tcp", "tcp4", "tcp6":
var la *TCPAddr
- if laddr != "" {
- if la, err = ResolveTCPAddr(net, laddr); err != nil {
- return nil, err
- }
- }
- l, err := ListenTCP(net, la)
- if err != nil {
- return nil, err
+ if a != nil {
+ la = a.(*TCPAddr)
}
- return l, nil
+ return ListenTCP(afnet, la)
case "unix", "unixpacket":
var la *UnixAddr
- if laddr != "" {
- if la, err = ResolveUnixAddr(net, laddr); err != nil {
- return nil, err
- }
- }
- l, err := ListenUnix(net, la)
- if err != nil {
- return nil, err
+ if a != nil {
+ la = a.(*UnixAddr)
}
- return l, nil
+ return ListenUnix(net, la)
}
return nil, UnknownNetworkError(net)
}
// ListenPacket announces on the local network address laddr.
// The network string net must be a packet-oriented network:
-// "udp", "udp4", "udp6", or "unixgram".
-func ListenPacket(net, laddr string) (c PacketConn, err error) {
- switch net {
+// "udp", "udp4", "udp6", "ip", "ip4", "ip6" or "unixgram".
+func ListenPacket(net, addr string) (PacketConn, error) {
+ afnet, a, err := resolveNetAddr("listen", net, addr)
+ if err != nil {
+ return nil, err
+ }
+ switch afnet {
case "udp", "udp4", "udp6":
var la *UDPAddr
- if laddr != "" {
- if la, err = ResolveUDPAddr(net, laddr); err != nil {
- return nil, err
- }
+ if a != nil {
+ la = a.(*UDPAddr)
}
- c, err := ListenUDP(net, la)
- if err != nil {
- return nil, err
+ return ListenUDP(net, la)
+ case "ip", "ip4", "ip6":
+ var la *IPAddr
+ if a != nil {
+ la = a.(*IPAddr)
}
- return c, nil
+ return ListenIP(net, la)
case "unixgram":
var la *UnixAddr
- if laddr != "" {
- if la, err = ResolveUnixAddr(net, laddr); err != nil {
- return nil, err
- }
+ if a != nil {
+ la = a.(*UnixAddr)
}
- c, err := DialUnix(net, la, nil)
- if err != nil {
- return nil, err
- }
- return c, nil
+ return DialUnix(net, la, nil)
}
-
- var rawnet string
- if rawnet, _, err = splitNetProto(net); err != nil {
- switch rawnet {
- case "ip", "ip4", "ip6":
- var la *IPAddr
- if laddr != "" {
- if la, err = ResolveIPAddr(rawnet, laddr); err != nil {
- return nil, err
- }
- }
- c, err := ListenIP(net, la)
- if err != nil {
- return nil, err
- }
- return c, nil
- }
- }
-
return nil, UnknownNetworkError(net)
}
diff --git a/libgo/go/net/dialgoogle_test.go b/libgo/go/net/dialgoogle_test.go
index 9ad1770dab7..81750a3d739 100644
--- a/libgo/go/net/dialgoogle_test.go
+++ b/libgo/go/net/dialgoogle_test.go
@@ -19,7 +19,7 @@ var ipv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present")
// fd is already connected to the destination, port 80.
// Run an HTTP request to fetch the appropriate page.
func fetchGoogle(t *testing.T, fd Conn, network, addr string) {
- req := []byte("GET /intl/en/privacy/ HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
+ req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
n, err := fd.Write(req)
buf := make([]byte, 1000)
diff --git a/libgo/go/net/dict/dict.go b/libgo/go/net/dict/dict.go
deleted file mode 100644
index e7f5290f552..00000000000
--- a/libgo/go/net/dict/dict.go
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package dict implements the Dictionary Server Protocol
-// as defined in RFC 2229.
-package dict
-
-import (
- "net/textproto"
- "strconv"
- "strings"
-)
-
-// A Client represents a client connection to a dictionary server.
-type Client struct {
- text *textproto.Conn
-}
-
-// Dial returns a new client connected to a dictionary server at
-// addr on the given network.
-func Dial(network, addr string) (*Client, error) {
- text, err := textproto.Dial(network, addr)
- if err != nil {
- return nil, err
- }
- _, _, err = text.ReadCodeLine(220)
- if err != nil {
- text.Close()
- return nil, err
- }
- return &Client{text: text}, nil
-}
-
-// Close closes the connection to the dictionary server.
-func (c *Client) Close() error {
- return c.text.Close()
-}
-
-// A Dict represents a dictionary available on the server.
-type Dict struct {
- Name string // short name of dictionary
- Desc string // long description
-}
-
-// Dicts returns a list of the dictionaries available on the server.
-func (c *Client) Dicts() ([]Dict, error) {
- id, err := c.text.Cmd("SHOW DB")
- if err != nil {
- return nil, err
- }
-
- c.text.StartResponse(id)
- defer c.text.EndResponse(id)
-
- _, _, err = c.text.ReadCodeLine(110)
- if err != nil {
- return nil, err
- }
- lines, err := c.text.ReadDotLines()
- if err != nil {
- return nil, err
- }
- _, _, err = c.text.ReadCodeLine(250)
-
- dicts := make([]Dict, len(lines))
- for i := range dicts {
- d := &dicts[i]
- a, _ := fields(lines[i])
- if len(a) < 2 {
- return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
- }
- d.Name = a[0]
- d.Desc = a[1]
- }
- return dicts, err
-}
-
-// A Defn represents a definition.
-type Defn struct {
- Dict Dict // Dict where definition was found
- Word string // Word being defined
- Text []byte // Definition text, typically multiple lines
-}
-
-// Define requests the definition of the given word.
-// The argument dict names the dictionary to use,
-// the Name field of a Dict returned by Dicts.
-//
-// The special dictionary name "*" means to look in all the
-// server's dictionaries.
-// The special dictionary name "!" means to look in all the
-// server's dictionaries in turn, stopping after finding the word
-// in one of them.
-func (c *Client) Define(dict, word string) ([]*Defn, error) {
- id, err := c.text.Cmd("DEFINE %s %q", dict, word)
- if err != nil {
- return nil, err
- }
-
- c.text.StartResponse(id)
- defer c.text.EndResponse(id)
-
- _, line, err := c.text.ReadCodeLine(150)
- if err != nil {
- return nil, err
- }
- a, _ := fields(line)
- if len(a) < 1 {
- return nil, textproto.ProtocolError("malformed response: " + line)
- }
- n, err := strconv.Atoi(a[0])
- if err != nil {
- return nil, textproto.ProtocolError("invalid definition count: " + a[0])
- }
- def := make([]*Defn, n)
- for i := 0; i < n; i++ {
- _, line, err = c.text.ReadCodeLine(151)
- if err != nil {
- return nil, err
- }
- a, _ := fields(line)
- if len(a) < 3 {
- // skip it, to keep protocol in sync
- i--
- n--
- def = def[0:n]
- continue
- }
- d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
- d.Text, err = c.text.ReadDotBytes()
- if err != nil {
- return nil, err
- }
- def[i] = d
- }
- _, _, err = c.text.ReadCodeLine(250)
- return def, err
-}
-
-// Fields returns the fields in s.
-// Fields are space separated unquoted words
-// or quoted with single or double quote.
-func fields(s string) ([]string, error) {
- var v []string
- i := 0
- for {
- for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
- i++
- }
- if i >= len(s) {
- break
- }
- if s[i] == '"' || s[i] == '\'' {
- q := s[i]
- // quoted string
- var j int
- for j = i + 1; ; j++ {
- if j >= len(s) {
- return nil, textproto.ProtocolError("malformed quoted string")
- }
- if s[j] == '\\' {
- j++
- continue
- }
- if s[j] == q {
- j++
- break
- }
- }
- v = append(v, unquote(s[i+1:j-1]))
- i = j
- } else {
- // atom
- var j int
- for j = i; j < len(s); j++ {
- if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
- break
- }
- }
- v = append(v, s[i:j])
- i = j
- }
- if i < len(s) {
- c := s[i]
- if c != ' ' && c != '\t' {
- return nil, textproto.ProtocolError("quotes not on word boundaries")
- }
- }
- }
- return v, nil
-}
-
-func unquote(s string) string {
- if strings.Index(s, "\\") < 0 {
- return s
- }
- b := []byte(s)
- w := 0
- for r := 0; r < len(b); r++ {
- c := b[r]
- if c == '\\' {
- r++
- c = b[r]
- }
- b[w] = c
- w++
- }
- return string(b[0:w])
-}
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index 7ecd135d206..495ef007fe2 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -22,15 +22,16 @@ type netFD struct {
closing bool
// immutable until Close
- sysfd int
- family int
- sotype int
- sysfile *os.File
- cr chan bool
- cw chan bool
- net string
- laddr Addr
- raddr Addr
+ sysfd int
+ family int
+ sotype int
+ isConnected bool
+ sysfile *os.File
+ cr chan bool
+ cw chan bool
+ net string
+ laddr Addr
+ raddr Addr
// owned by client
rdeadline int64
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index 6e37b4eb6f1..f00459f0baf 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -228,14 +228,15 @@ type netFD struct {
closing bool
// immutable until Close
- sysfd syscall.Handle
- family int
- sotype int
- net string
- laddr Addr
- raddr Addr
- resultc [2]chan ioResult // read/write completion results
- errnoc [2]chan error // read/write submit or cancel operation errors
+ sysfd syscall.Handle
+ family int
+ sotype int
+ isConnected bool
+ net string
+ laddr Addr
+ raddr Addr
+ resultc [2]chan ioResult // read/write completion results
+ errnoc [2]chan error // read/write submit or cancel operation errors
// owned by client
rdeadline int64
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index 1d70672695c..c9f02401757 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -116,6 +116,10 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
return nil, errors.New("http: nil Request.URL")
}
+ if req.RequestURI != "" {
+ return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
+ }
+
// Most the callers of send (Get, Post, et al) don't need
// Headers, leaving it uninitialized. We guarantee to the
// Transport that this has been initialized, though.
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index c74611011a8..aa0bf4be676 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -428,3 +428,15 @@ func TestClientInsecureTransport(t *testing.T) {
}
}
}
+
+func TestClientErrorWithRequestURI(t *testing.T) {
+ req, _ := NewRequest("GET", "http://localhost:1234/", nil)
+ req.RequestURI = "/this/field/is/illegal/and/should/error/"
+ _, err := DefaultClient.Do(req)
+ if err == nil {
+ t.Fatalf("expected an error")
+ }
+ if !strings.Contains(err.Error(), "RequestURI") {
+ t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
+ }
+}
diff --git a/libgo/go/net/http/readrequest_test.go b/libgo/go/net/http/readrequest_test.go
index da3e4050fe1..2e03c658aa9 100644
--- a/libgo/go/net/http/readrequest_test.go
+++ b/libgo/go/net/http/readrequest_test.go
@@ -64,6 +64,7 @@ var reqTests = []reqTest{
Close: false,
ContentLength: 7,
Host: "www.techcrunch.com",
+ RequestURI: "http://www.techcrunch.com/",
},
"abcdef\n",
@@ -89,6 +90,7 @@ var reqTests = []reqTest{
Close: false,
ContentLength: 0,
Host: "foo.com",
+ RequestURI: "/",
},
noBody,
@@ -114,6 +116,7 @@ var reqTests = []reqTest{
Close: false,
ContentLength: 0,
Host: "test",
+ RequestURI: "//user@host/is/actually/a/path/",
},
noBody,
@@ -163,6 +166,7 @@ var reqTests = []reqTest{
Header: Header{},
ContentLength: -1,
Host: "foo.com",
+ RequestURI: "/",
},
"foobar",
@@ -171,6 +175,78 @@ var reqTests = []reqTest{
},
noError,
},
+
+ // CONNECT request with domain name:
+ {
+ "CONNECT www.google.com:443 HTTP/1.1\r\n\r\n",
+
+ &Request{
+ Method: "CONNECT",
+ URL: &url.URL{
+ Host: "www.google.com:443",
+ },
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: Header{},
+ Close: false,
+ ContentLength: 0,
+ Host: "www.google.com:443",
+ RequestURI: "www.google.com:443",
+ },
+
+ noBody,
+ noTrailer,
+ noError,
+ },
+
+ // CONNECT request with IP address:
+ {
+ "CONNECT 127.0.0.1:6060 HTTP/1.1\r\n\r\n",
+
+ &Request{
+ Method: "CONNECT",
+ URL: &url.URL{
+ Host: "127.0.0.1:6060",
+ },
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: Header{},
+ Close: false,
+ ContentLength: 0,
+ Host: "127.0.0.1:6060",
+ RequestURI: "127.0.0.1:6060",
+ },
+
+ noBody,
+ noTrailer,
+ noError,
+ },
+
+ // CONNECT request for RPC:
+ {
+ "CONNECT /_goRPC_ HTTP/1.1\r\n\r\n",
+
+ &Request{
+ Method: "CONNECT",
+ URL: &url.URL{
+ Path: "/_goRPC_",
+ },
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: Header{},
+ Close: false,
+ ContentLength: 0,
+ Host: "",
+ RequestURI: "/_goRPC_",
+ },
+
+ noBody,
+ noTrailer,
+ noError,
+ },
}
func TestReadRequest(t *testing.T) {
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 5a4e739073a..5f8c00086be 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -153,6 +153,12 @@ type Request struct {
// This field is ignored by the HTTP client.
RemoteAddr string
+ // RequestURI is the unmodified Request-URI of the
+ // Request-Line (RFC 2616, Section 5.1) as sent by the client
+ // to a server. Usually the URL field should be used instead.
+ // It is an error to set this field in an HTTP client request.
+ RequestURI string
+
// TLS allows HTTP servers and other software to record
// information about the TLS connection on which the request
// was received. This field is not filled in by ReadRequest.
@@ -305,6 +311,9 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
ruri := req.URL.RequestURI()
if usingProxy && req.URL.Scheme != "" && req.URL.Opaque == "" {
ruri = req.URL.Scheme + "://" + host + ruri
+ } else if req.Method == "CONNECT" && req.URL.Path == "" {
+ // CONNECT requests normally give just the host and port, not a full URL.
+ ruri = host
}
// TODO(bradfitz): escape at least newlines in ruri?
@@ -456,17 +465,36 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
if f = strings.SplitN(s, " ", 3); len(f) < 3 {
return nil, &badStringError{"malformed HTTP request", s}
}
- var rawurl string
- req.Method, rawurl, req.Proto = f[0], f[1], f[2]
+ req.Method, req.RequestURI, req.Proto = f[0], f[1], f[2]
+ rawurl := req.RequestURI
var ok bool
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
return nil, &badStringError{"malformed HTTP version", req.Proto}
}
+ // CONNECT requests are used two different ways, and neither uses a full URL:
+ // The standard use is to tunnel HTTPS through an HTTP proxy.
+ // It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is
+ // just the authority section of a URL. This information should go in req.URL.Host.
+ //
+ // The net/rpc package also uses CONNECT, but there the parameter is a path
+ // that starts with a slash. It can be parsed with the regular URL parser,
+ // and the path will end up in req.URL.Path, where it needs to be in order for
+ // RPC to work.
+ justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/")
+ if justAuthority {
+ rawurl = "http://" + rawurl
+ }
+
if req.URL, err = url.ParseRequest(rawurl); err != nil {
return nil, err
}
+ if justAuthority {
+ // Strip the bogus "http://" back off.
+ req.URL.Scheme = ""
+ }
+
// Subsequent lines: Key: value.
mimeHeader, err := tp.ReadMIMEHeader()
if err != nil {
@@ -584,7 +612,7 @@ func (r *Request) ParseForm() (err error) {
return errors.New("missing form body")
}
ct := r.Header.Get("Content-Type")
- ct, _, err := mime.ParseMediaType(ct)
+ ct, _, err = mime.ParseMediaType(ct)
switch {
case ct == "application/x-www-form-urlencoded":
var reader io.Reader = r.Body
@@ -624,8 +652,6 @@ func (r *Request) ParseForm() (err error) {
// Clean this up and write more tests.
// request_test.go contains the start of this,
// in TestRequestMultipartCallOrder.
- default:
- return &badStringError{"unknown Content-Type", ct}
}
}
return err
diff --git a/libgo/go/net/http/request_test.go b/libgo/go/net/http/request_test.go
index 7b78645169e..7a3556d0367 100644
--- a/libgo/go/net/http/request_test.go
+++ b/libgo/go/net/http/request_test.go
@@ -46,19 +46,19 @@ func TestPostQuery(t *testing.T) {
type stringMap map[string][]string
type parseContentTypeTest struct {
+ shouldError bool
contentType stringMap
}
var parseContentTypeTests = []parseContentTypeTest{
- {contentType: stringMap{"Content-Type": {"text/plain"}}},
- {contentType: stringMap{}}, // Non-existent keys are not placed. The value nil is illegal.
- {contentType: stringMap{"Content-Type": {"text/plain; boundary="}}},
- {
- contentType: stringMap{"Content-Type": {"application/unknown"}},
- },
+ {false, stringMap{"Content-Type": {"text/plain"}}},
+ // Non-existent keys are not placed. The value nil is illegal.
+ {true, stringMap{}},
+ {true, stringMap{"Content-Type": {"text/plain; boundary="}}},
+ {false, stringMap{"Content-Type": {"application/unknown"}}},
}
-func TestParseFormBadContentType(t *testing.T) {
+func TestParseFormUnknownContentType(t *testing.T) {
for i, test := range parseContentTypeTests {
req := &Request{
Method: "POST",
@@ -66,8 +66,11 @@ func TestParseFormBadContentType(t *testing.T) {
Body: ioutil.NopCloser(bytes.NewBufferString("body")),
}
err := req.ParseForm()
- if err == nil {
+ switch {
+ case err == nil && test.shouldError:
t.Errorf("test %d should have returned error", i)
+ case err != nil && !test.shouldError:
+ t.Errorf("test %d should not have returned error, got %v", i, err)
}
}
}
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 1b9ad1b85c5..4de070f01f1 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -494,12 +494,6 @@ func (pc *persistConn) isBroken() bool {
return pc.broken
}
-func (pc *persistConn) expectingResponse() bool {
- pc.lk.Lock()
- defer pc.lk.Unlock()
- return pc.numExpectedResponses > 0
-}
-
var remoteSideClosedFunc func(error) bool // or nil to use default
func remoteSideClosed(err error) bool {
@@ -518,14 +512,18 @@ func (pc *persistConn) readLoop() {
for alive {
pb, err := pc.br.Peek(1)
- if !pc.expectingResponse() {
+
+ pc.lk.Lock()
+ if pc.numExpectedResponses == 0 {
+ pc.closeLocked()
+ pc.lk.Unlock()
if len(pb) > 0 {
log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
string(pb), err)
}
- pc.close()
return
}
+ pc.lk.Unlock()
rc := <-pc.reqch
@@ -649,6 +647,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
func (pc *persistConn) close() {
pc.lk.Lock()
defer pc.lk.Unlock()
+ pc.closeLocked()
+}
+
+func (pc *persistConn) closeLocked() {
pc.broken = true
pc.conn.Close()
pc.mutateHeaderFunc = nil
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index ff12fa2d014..321da52e278 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -304,6 +304,62 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
}
}
+// Test for http://golang.org/issue/2616 (appropriate issue number)
+// This fails pretty reliably with GOMAXPROCS=100 or something high.
+func TestStressSurpriseServerCloses(t *testing.T) {
+ if testing.Short() {
+ t.Logf("skipping test in short mode")
+ return
+ }
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Content-Length", "5")
+ w.Header().Set("Content-Type", "text/plain")
+ w.Write([]byte("Hello"))
+ w.(Flusher).Flush()
+ conn, buf, _ := w.(Hijacker).Hijack()
+ buf.Flush()
+ conn.Close()
+ }))
+ defer ts.Close()
+
+ tr := &Transport{DisableKeepAlives: false}
+ c := &Client{Transport: tr}
+
+ // Do a bunch of traffic from different goroutines. Send to activityc
+ // after each request completes, regardless of whether it failed.
+ const (
+ numClients = 50
+ reqsPerClient = 250
+ )
+ activityc := make(chan bool)
+ for i := 0; i < numClients; i++ {
+ go func() {
+ for i := 0; i < reqsPerClient; i++ {
+ res, err := c.Get(ts.URL)
+ if err == nil {
+ // We expect errors since the server is
+ // hanging up on us after telling us to
+ // send more requests, so we don't
+ // actually care what the error is.
+ // But we want to close the body in cases
+ // where we won the race.
+ res.Body.Close()
+ }
+ activityc <- true
+ }
+ }()
+ }
+
+ // Make sure all the request come back, one way or another.
+ for i := 0; i < numClients*reqsPerClient; i++ {
+ select {
+ case <-activityc:
+ case <-time.After(5 * time.Second):
+ t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
+ }
+ }
+}
+
// TestTransportHeadResponses verifies that we deal with Content-Lengths
// with no bodies properly
func TestTransportHeadResponses(t *testing.T) {
diff --git a/libgo/go/net/ipraw_test.go b/libgo/go/net/ipraw_test.go
index c74bfcd6c79..f9401c1104e 100644
--- a/libgo/go/net/ipraw_test.go
+++ b/libgo/go/net/ipraw_test.go
@@ -2,121 +2,191 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// TODO(cw): ListenPacket test, Read() test, ipv6 test &
-// Dial()/Listen() level tests
-
package net
import (
"bytes"
- "flag"
"os"
"testing"
"time"
)
-const ICMP_ECHO_REQUEST = 8
-const ICMP_ECHO_REPLY = 0
-
-// returns a suitable 'ping request' packet, with id & seq and a
-// payload length of pktlen
-func makePingRequest(id, seq, pktlen int, filler []byte) []byte {
- p := make([]byte, pktlen)
- copy(p[8:], bytes.Repeat(filler, (pktlen-8)/len(filler)+1))
-
- p[0] = ICMP_ECHO_REQUEST // type
- p[1] = 0 // code
- p[2] = 0 // cksum
- p[3] = 0 // cksum
- p[4] = uint8(id >> 8) // id
- p[5] = uint8(id & 0xff) // id
- p[6] = uint8(seq >> 8) // sequence
- p[7] = uint8(seq & 0xff) // sequence
-
- // calculate icmp checksum
- cklen := len(p)
- s := uint32(0)
- for i := 0; i < (cklen - 1); i += 2 {
- s += uint32(p[i+1])<<8 | uint32(p[i])
- }
- if cklen&1 == 1 {
- s += uint32(p[cklen-1])
- }
- s = (s >> 16) + (s & 0xffff)
- s = s + (s >> 16)
-
- // place checksum back in header; using ^= avoids the
- // assumption the checksum bytes are zero
- p[2] ^= uint8(^s & 0xff)
- p[3] ^= uint8(^s >> 8)
-
- return p
-}
-
-func parsePingReply(p []byte) (id, seq int) {
- id = int(p[4])<<8 | int(p[5])
- seq = int(p[6])<<8 | int(p[7])
- return
+var icmpTests = []struct {
+ net string
+ laddr string
+ raddr string
+ ipv6 bool
+}{
+ {"ip4:icmp", "", "127.0.0.1", false},
+ {"ip6:icmp", "", "::1", true},
}
-var srchost = flag.String("srchost", "", "Source of the ICMP ECHO request")
-
-// 127.0.0.1 because this is an IPv4-specific test.
-var dsthost = flag.String("dsthost", "127.0.0.1", "Destination for the ICMP ECHO request")
-
-// test (raw) IP socket using ICMP
func TestICMP(t *testing.T) {
if os.Getuid() != 0 {
t.Logf("test disabled; must be root")
return
}
- var (
- laddr *IPAddr
- err error
- )
- if *srchost != "" {
- laddr, err = ResolveIPAddr("ip4", *srchost)
- if err != nil {
- t.Fatalf(`net.ResolveIPAddr("ip4", %v") = %v, %v`, *srchost, laddr, err)
+ seqnum := 61455
+ for _, tt := range icmpTests {
+ if tt.ipv6 && !supportsIPv6 {
+ continue
}
+ id := os.Getpid() & 0xffff
+ seqnum++
+ echo := newICMPEchoRequest(tt.ipv6, id, seqnum, 128, []byte("Go Go Gadget Ping!!!"))
+ exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, tt.ipv6, echo)
}
+}
- raddr, err := ResolveIPAddr("ip4", *dsthost)
+func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo []byte) {
+ c, err := ListenPacket(net, laddr)
if err != nil {
- t.Fatalf(`net.ResolveIPAddr("ip4", %v") = %v, %v`, *dsthost, raddr, err)
+ t.Errorf("ListenPacket(%#q, %#q) failed: %v", net, laddr, err)
+ return
}
+ c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+ defer c.Close()
- c, err := ListenIP("ip4:icmp", laddr)
+ ra, err := ResolveIPAddr(net, raddr)
if err != nil {
- t.Fatalf(`net.ListenIP("ip4:icmp", %v) = %v, %v`, *srchost, c, err)
+ t.Errorf("ResolveIPAddr(%#q, %#q) failed: %v", net, raddr, err)
+ return
}
- sendid := os.Getpid() & 0xffff
- const sendseq = 61455
- const pingpktlen = 128
- sendpkt := makePingRequest(sendid, sendseq, pingpktlen, []byte("Go Go Gadget Ping!!!"))
+ waitForReady := make(chan bool)
+ go icmpEchoTransponder(t, net, raddr, ipv6, waitForReady)
+ <-waitForReady
- n, err := c.WriteToIP(sendpkt, raddr)
- if err != nil || n != pingpktlen {
- t.Fatalf(`net.WriteToIP(..., %v) = %v, %v`, raddr, n, err)
+ _, err = c.WriteTo(echo, ra)
+ if err != nil {
+ t.Errorf("WriteTo failed: %v", err)
+ return
}
+ reply := make([]byte, 256)
+ for {
+ _, _, err := c.ReadFrom(reply)
+ if err != nil {
+ t.Errorf("ReadFrom failed: %v", err)
+ return
+ }
+ if !ipv6 && reply[0] != ICMP4_ECHO_REPLY {
+ continue
+ }
+ if ipv6 && reply[0] != ICMP6_ECHO_REPLY {
+ continue
+ }
+ xid, xseqnum := parseICMPEchoReply(echo)
+ rid, rseqnum := parseICMPEchoReply(reply)
+ if rid != xid || rseqnum != xseqnum {
+ t.Errorf("ID = %v, Seqnum = %v, want ID = %v, Seqnum = %v", rid, rseqnum, xid, xseqnum)
+ return
+ }
+ break
+ }
+}
+
+func icmpEchoTransponder(t *testing.T, net, raddr string, ipv6 bool, waitForReady chan bool) {
+ c, err := Dial(net, raddr)
+ if err != nil {
+ waitForReady <- true
+ t.Errorf("Dial(%#q, %#q) failed: %v", net, raddr, err)
+ return
+ }
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
- resp := make([]byte, 1024)
+ defer c.Close()
+ waitForReady <- true
+
+ echo := make([]byte, 256)
+ var nr int
for {
- n, from, err := c.ReadFrom(resp)
+ nr, err = c.Read(echo)
if err != nil {
- t.Fatalf(`ReadFrom(...) = %v, %v, %v`, n, from, err)
+ t.Errorf("Read failed: %v", err)
+ return
}
- if resp[0] != ICMP_ECHO_REPLY {
+ if !ipv6 && echo[0] != ICMP4_ECHO_REQUEST {
continue
}
- rcvid, rcvseq := parsePingReply(resp)
- if rcvid != sendid || rcvseq != sendseq {
- t.Fatalf(`Ping reply saw id,seq=0x%x,0x%x (expected 0x%x, 0x%x)`, rcvid, rcvseq, sendid, sendseq)
+ if ipv6 && echo[0] != ICMP6_ECHO_REQUEST {
+ continue
}
+ break
+ }
+
+ if !ipv6 {
+ echo[0] = ICMP4_ECHO_REPLY
+ } else {
+ echo[0] = ICMP6_ECHO_REPLY
+ }
+
+ _, err = c.Write(echo[:nr])
+ if err != nil {
+ t.Errorf("Write failed: %v", err)
return
}
- t.Fatalf("saw no ping return")
+}
+
+const (
+ ICMP4_ECHO_REQUEST = 8
+ ICMP4_ECHO_REPLY = 0
+ ICMP6_ECHO_REQUEST = 128
+ ICMP6_ECHO_REPLY = 129
+)
+
+func newICMPEchoRequest(ipv6 bool, id, seqnum, msglen int, filler []byte) []byte {
+ if !ipv6 {
+ return newICMPv4EchoRequest(id, seqnum, msglen, filler)
+ }
+ return newICMPv6EchoRequest(id, seqnum, msglen, filler)
+}
+
+func newICMPv4EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
+ b := newICMPInfoMessage(id, seqnum, msglen, filler)
+ b[0] = ICMP4_ECHO_REQUEST
+
+ // calculate ICMP checksum
+ cklen := len(b)
+ s := uint32(0)
+ for i := 0; i < cklen-1; i += 2 {
+ s += uint32(b[i+1])<<8 | uint32(b[i])
+ }
+ if cklen&1 == 1 {
+ s += uint32(b[cklen-1])
+ }
+ s = (s >> 16) + (s & 0xffff)
+ s = s + (s >> 16)
+ // place checksum back in header; using ^= avoids the
+ // assumption the checksum bytes are zero
+ b[2] ^= uint8(^s & 0xff)
+ b[3] ^= uint8(^s >> 8)
+
+ return b
+}
+
+func newICMPv6EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
+ b := newICMPInfoMessage(id, seqnum, msglen, filler)
+ b[0] = ICMP6_ECHO_REQUEST
+ return b
+}
+
+func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
+ b := make([]byte, msglen)
+ copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
+ b[0] = 0 // type
+ b[1] = 0 // code
+ b[2] = 0 // checksum
+ b[3] = 0 // checksum
+ b[4] = uint8(id >> 8) // identifier
+ b[5] = uint8(id & 0xff) // identifier
+ b[6] = uint8(seqnum >> 8) // sequence number
+ b[7] = uint8(seqnum & 0xff) // sequence number
+ return b
+}
+
+func parseICMPEchoReply(b []byte) (id, seqnum int) {
+ id = int(b[4])<<8 | int(b[5])
+ seqnum = int(b[6])<<8 | int(b[7])
+ return
}
diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go
index 58df607e3be..859153c2aad 100644
--- a/libgo/go/net/iprawsock_plan9.go
+++ b/libgo/go/net/iprawsock_plan9.go
@@ -32,13 +32,13 @@ func (c *IPConn) SetWriteDeadline(t time.Time) error {
// Implementation of the Conn interface - see Conn for documentation.
-// Read implements the net.Conn Read method.
-func (c *IPConn) Read(b []byte) (n int, err error) {
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
return 0, os.EPLAN9
}
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err error) {
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
return 0, os.EPLAN9
}
@@ -59,10 +59,20 @@ func (c *IPConn) RemoteAddr() Addr {
// IP-specific methods.
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
- err = os.EPLAN9
- return
+// ReadFromIP reads a IP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
+ return 0, nil, os.EPLAN9
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
+ return 0, nil, os.EPLAN9
}
// WriteToIP writes a IP packet to addr via c, copying the payload from b.
@@ -71,23 +81,18 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
// an error with Timeout() == true after a fixed time limit;
// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
return 0, os.EPLAN9
}
-// WriteTo implements the net.PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
return 0, os.EPLAN9
}
-func splitNetProto(netProto string) (net string, proto int, err error) {
- err = os.EPLAN9
- return
-}
-
// DialIP connects to the remote address raddr on the network protocol netProto,
// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
-func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
return nil, os.EPLAN9
}
@@ -95,6 +100,6 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
// local address laddr. The returned connection c's ReadFrom
// and WriteTo methods can be used to receive and send IP
// packets with per-packet addressing.
-func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err error) {
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
return nil, os.EPLAN9
}
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index e4f755bc785..c34ffeb121d 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -9,7 +9,6 @@
package net
import (
- "errors"
"os"
"syscall"
"time"
@@ -58,14 +57,14 @@ func (c *IPConn) ok() bool { return c != nil && c.fd != nil }
// Implementation of the Conn interface - see Conn for documentation.
-// Read implements the net.Conn Read method.
-func (c *IPConn) Read(b []byte) (n int, err error) {
- n, _, err = c.ReadFrom(b)
- return
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
+ n, _, err := c.ReadFrom(b)
+ return n, err
}
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err error) {
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
if !c.ok() {
return 0, os.EINVAL
}
@@ -98,7 +97,7 @@ func (c *IPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetDeadline implements the net.Conn SetDeadline method.
+// SetDeadline implements the Conn SetDeadline method.
func (c *IPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
@@ -106,7 +105,7 @@ func (c *IPConn) SetDeadline(t time.Time) error {
return setDeadline(c.fd, t)
}
-// SetReadDeadline implements the net.Conn SetReadDeadline method.
+// SetReadDeadline implements the Conn SetReadDeadline method.
func (c *IPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
@@ -114,7 +113,7 @@ func (c *IPConn) SetReadDeadline(t time.Time) error {
return setReadDeadline(c.fd, t)
}
-// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
func (c *IPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
@@ -149,12 +148,13 @@ func (c *IPConn) SetWriteBuffer(bytes int) error {
// ReadFromIP can be made to time out and return an error with
// Timeout() == true after a fixed time limit; see SetDeadline and
// SetReadDeadline.
-func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err error) {
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
if !c.ok() {
return 0, nil, os.EINVAL
}
// TODO(cw,rsc): consider using readv if we know the family
// type to avoid the header trim/copy
+ var addr *IPAddr
n, sa, err := c.fd.ReadFrom(b)
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
@@ -167,11 +167,11 @@ func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err error) {
case *syscall.SockaddrInet6:
addr = &IPAddr{sa.Addr[0:]}
}
- return
+ return n, addr, err
}
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
if !c.ok() {
return 0, nil, os.EINVAL
}
@@ -185,52 +185,35 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
// an error with Timeout() == true after a fixed time limit;
// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
if !c.ok() {
return 0, os.EINVAL
}
- sa, err1 := addr.sockaddr(c.fd.family)
- if err1 != nil {
- return 0, &OpError{Op: "write", Net: "ip", Addr: addr, Err: err1}
+ sa, err := addr.sockaddr(c.fd.family)
+ if err != nil {
+ return 0, &OpError{"write", c.fd.net, addr, err}
}
return c.fd.WriteTo(b, sa)
}
-// WriteTo implements the net.PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
if !c.ok() {
return 0, os.EINVAL
}
a, ok := addr.(*IPAddr)
if !ok {
- return 0, &OpError{"writeto", "ip", addr, os.EINVAL}
+ return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
}
return c.WriteToIP(b, a)
}
-func splitNetProto(netProto string) (net string, proto int, err error) {
- i := last(netProto, ':')
- if i < 0 { // no colon
- return "", 0, errors.New("no IP protocol specified")
- }
- net = netProto[0:i]
- protostr := netProto[i+1:]
- proto, i, ok := dtoi(protostr, 0)
- if !ok || i != len(protostr) {
- proto, err = lookupProtocol(protostr)
- if err != nil {
- return "", 0, err
- }
- }
- return net, proto, nil
-}
-
// DialIP connects to the remote address raddr on the network protocol netProto,
// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
-func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
- net, proto, err := splitNetProto(netProto)
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+ net, proto, err := parseDialNetwork(netProto)
if err != nil {
- return
+ return nil, err
}
switch net {
case "ip", "ip4", "ip6":
@@ -238,11 +221,11 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
return nil, UnknownNetworkError(net)
}
if raddr == nil {
- return nil, &OpError{"dial", "ip", nil, errMissingAddress}
+ return nil, &OpError{"dial", netProto, nil, errMissingAddress}
}
- fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
- if e != nil {
- return nil, e
+ fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+ if err != nil {
+ return nil, err
}
return newIPConn(fd), nil
}
@@ -251,19 +234,19 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
// local address laddr. The returned connection c's ReadFrom
// and WriteTo methods can be used to receive and send IP
// packets with per-packet addressing.
-func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err error) {
- net, proto, err := splitNetProto(netProto)
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+ net, proto, err := parseDialNetwork(netProto)
if err != nil {
- return
+ return nil, err
}
switch net {
case "ip", "ip4", "ip6":
default:
return nil, UnknownNetworkError(net)
}
- fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
- if e != nil {
- return nil, e
+ fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+ if err != nil {
+ return nil, err
}
return newIPConn(fd), nil
}
diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go
index 645aa6d2493..c0bb9225a7d 100644
--- a/libgo/go/net/lookup_plan9.go
+++ b/libgo/go/net/lookup_plan9.go
@@ -69,6 +69,11 @@ func queryDNS(addr string, typ string) (res []string, err error) {
return query("/net/dns", addr+" "+typ, 1024)
}
+func lookupProtocol(name string) (proto int, err error) {
+ // TODO: Implement this
+ return 0, os.EPLAN9
+}
+
func lookupHost(host string) (addrs []string, err error) {
// Use /net/cs insead of /net/dns because cs knows about
// host names in local network (e.g. from /lib/ndb/local)
diff --git a/libgo/go/net/rpc/client.go b/libgo/go/net/rpc/client.go
index 6fb414e089c..abc1e59cd51 100644
--- a/libgo/go/net/rpc/client.go
+++ b/libgo/go/net/rpc/client.go
@@ -145,6 +145,7 @@ func (call *Call) done() {
default:
// We don't want to block here. It is the caller's responsibility to make
// sure the channel has enough buffer space. See comment in Go().
+ log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
}
}
diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go
index ae688c0f8ca..b05c63c0563 100644
--- a/libgo/go/net/rpc/server_test.go
+++ b/libgo/go/net/rpc/server_test.go
@@ -467,13 +467,16 @@ func TestCountMallocsOverHTTP(t *testing.T) {
fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
}
-type writeCrasher struct{}
+type writeCrasher struct {
+ done chan bool
+}
func (writeCrasher) Close() error {
return nil
}
-func (writeCrasher) Read(p []byte) (int, error) {
+func (w *writeCrasher) Read(p []byte) (int, error) {
+ <-w.done
return 0, io.EOF
}
@@ -482,7 +485,8 @@ func (writeCrasher) Write(p []byte) (int, error) {
}
func TestClientWriteError(t *testing.T) {
- c := NewClient(writeCrasher{})
+ w := &writeCrasher{done: make(chan bool)}
+ c := NewClient(w)
res := false
err := c.Call("foo", 1, &res)
if err == nil {
@@ -491,6 +495,7 @@ func TestClientWriteError(t *testing.T) {
if err.Error() != "fake write failure" {
t.Error("unexpected value of error:", err)
}
+ w.done <- true
}
func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
@@ -513,7 +518,7 @@ func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
go func() {
reply := new(Reply)
for atomic.AddInt32(&N, -1) >= 0 {
- err = client.Call("Arith.Add", args, reply)
+ err := client.Call("Arith.Add", args, reply)
if err != nil {
b.Fatalf("rpc error: Add: expected no error but got string %q", err.Error())
}
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index 2f3210b4288..867e328f12e 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -49,6 +49,7 @@ func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscal
fd.Close()
return nil, err
}
+ fd.isConnected = true
}
sa, _ := syscall.Getsockname(s)
diff --git a/libgo/go/net/sockopt.go b/libgo/go/net/sockopt.go
index 59f9af5f30a..3d0f8dd7a89 100644
--- a/libgo/go/net/sockopt.go
+++ b/libgo/go/net/sockopt.go
@@ -117,12 +117,20 @@ func setWriteBuffer(fd *netFD, bytes int) error {
}
func setReadDeadline(fd *netFD, t time.Time) error {
- fd.rdeadline = t.UnixNano()
+ if t.IsZero() {
+ fd.rdeadline = 0
+ } else {
+ fd.rdeadline = t.UnixNano()
+ }
return nil
}
func setWriteDeadline(fd *netFD, t time.Time) error {
- fd.wdeadline = t.UnixNano()
+ if t.IsZero() {
+ fd.wdeadline = 0
+ } else {
+ fd.wdeadline = t.UnixNano()
+ }
return nil
}
diff --git a/libgo/go/net/tcpsock_plan9.go b/libgo/go/net/tcpsock_plan9.go
index 288ec056ab0..f2444a4d96f 100644
--- a/libgo/go/net/tcpsock_plan9.go
+++ b/libgo/go/net/tcpsock_plan9.go
@@ -60,7 +60,7 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
return nil, UnknownNetworkError(net)
}
if raddr == nil {
- return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
+ return nil, &OpError{"dial", net, nil, errMissingAddress}
}
c1, err := dialPlan9(net, laddr, raddr)
if err != nil {
@@ -87,7 +87,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
return nil, UnknownNetworkError(net)
}
if laddr == nil {
- return nil, &OpError{"listen", "tcp", nil, errMissingAddress}
+ return nil, &OpError{"listen", net, nil, errMissingAddress}
}
l1, err := listenPlan9(net, laddr)
if err != nil {
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index 91816fa9d46..65ec493039c 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -225,7 +225,7 @@ func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
// as the local address for the connection.
func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
if raddr == nil {
- return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
+ return nil, &OpError{"dial", net, nil, errMissingAddress}
}
fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
if e != nil {
@@ -253,7 +253,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
err = syscall.Listen(fd.sysfd, listenerBacklog)
if err != nil {
closesocket(fd.sysfd)
- return nil, &OpError{"listen", "tcp", laddr, err}
+ return nil, &OpError{"listen", net, laddr, err}
}
l = new(TCPListener)
l.fd = fd
diff --git a/libgo/go/net/timeout_test.go b/libgo/go/net/timeout_test.go
index 11db012ff57..bae37c86b2e 100644
--- a/libgo/go/net/timeout_test.go
+++ b/libgo/go/net/timeout_test.go
@@ -77,3 +77,30 @@ func TestTimeoutTCP(t *testing.T) {
testTimeout(t, "tcp", addr, false)
<-done
}
+
+func TestDeadlineReset(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ return
+ }
+ ln, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+ tl := ln.(*TCPListener)
+ tl.SetDeadline(time.Now().Add(1 * time.Minute))
+ tl.SetDeadline(time.Time{}) // reset it
+ errc := make(chan error, 1)
+ go func() {
+ _, err := ln.Accept()
+ errc <- err
+ }()
+ select {
+ case <-time.After(50 * time.Millisecond):
+ // Pass.
+ case err := <-errc:
+ // Accept should never return; we never
+ // connected to it.
+ t.Errorf("unexpected return from Accept; err=%v", err)
+ }
+}
diff --git a/libgo/go/net/udp_test.go b/libgo/go/net/udp_test.go
new file mode 100644
index 00000000000..6ba762b1f78
--- /dev/null
+++ b/libgo/go/net/udp_test.go
@@ -0,0 +1,87 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "runtime"
+ "testing"
+)
+
+func TestWriteToUDP(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ return
+ }
+
+ l, err := ListenPacket("udp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+ defer l.Close()
+
+ testWriteToConn(t, l.LocalAddr().String())
+ testWriteToPacketConn(t, l.LocalAddr().String())
+}
+
+func testWriteToConn(t *testing.T, raddr string) {
+ c, err := Dial("udp", raddr)
+ if err != nil {
+ t.Fatalf("Dial failed: %v", err)
+ }
+ defer c.Close()
+
+ ra, err := ResolveUDPAddr("udp", raddr)
+ if err != nil {
+ t.Fatalf("ResolveUDPAddr failed: %v", err)
+ }
+
+ _, err = c.(*UDPConn).WriteToUDP([]byte("Connection-oriented mode socket"), ra)
+ if err == nil {
+ t.Fatal("WriteToUDP should be failed")
+ }
+ if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+ t.Fatalf("WriteToUDP should be failed as ErrWriteToConnected: %v", err)
+ }
+
+ _, err = c.(*UDPConn).WriteTo([]byte("Connection-oriented mode socket"), ra)
+ if err == nil {
+ t.Fatal("WriteTo should be failed")
+ }
+ if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+ t.Fatalf("WriteTo should be failed as ErrWriteToConnected: %v", err)
+ }
+
+ _, err = c.Write([]byte("Connection-oriented mode socket"))
+ if err != nil {
+ t.Fatalf("Write failed: %v", err)
+ }
+}
+
+func testWriteToPacketConn(t *testing.T, raddr string) {
+ c, err := ListenPacket("udp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("ListenPacket failed: %v", err)
+ }
+ defer c.Close()
+
+ ra, err := ResolveUDPAddr("udp", raddr)
+ if err != nil {
+ t.Fatalf("ResolveUDPAddr failed: %v", err)
+ }
+
+ _, err = c.(*UDPConn).WriteToUDP([]byte("Connection-less mode socket"), ra)
+ if err != nil {
+ t.Fatalf("WriteToUDP failed: %v", err)
+ }
+
+ _, err = c.WriteTo([]byte("Connection-less mode socket"), ra)
+ if err != nil {
+ t.Fatalf("WriteTo failed: %v", err)
+ }
+
+ _, err = c.(*UDPConn).Write([]byte("Connection-less mode socket"))
+ if err == nil {
+ t.Fatal("Write should be failed")
+ }
+}
diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go
index 246c9ad94b5..573438f85de 100644
--- a/libgo/go/net/udpsock_plan9.go
+++ b/libgo/go/net/udpsock_plan9.go
@@ -110,7 +110,7 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
}
a, ok := addr.(*UDPAddr)
if !ok {
- return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+ return 0, &OpError{"write", c.dir, addr, os.EINVAL}
}
return c.WriteToUDP(b, a)
}
@@ -125,7 +125,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
return nil, UnknownNetworkError(net)
}
if raddr == nil {
- return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+ return nil, &OpError{"dial", net, nil, errMissingAddress}
}
c1, err := dialPlan9(net, laddr, raddr)
if err != nil {
@@ -173,7 +173,7 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
return nil, UnknownNetworkError(net)
}
if laddr == nil {
- return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+ return nil, &OpError{"listen", net, nil, errMissingAddress}
}
l, err := listenPlan9(net, laddr)
if err != nil {
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index 0b5bc16f822..fa3d29adfa8 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -9,11 +9,14 @@
package net
import (
+ "errors"
"os"
"syscall"
"time"
)
+var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
+
func sockaddrToUDP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
@@ -178,25 +181,28 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
// an error with Timeout() == true after a fixed time limit;
// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
-func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
if !c.ok() {
return 0, os.EINVAL
}
- sa, err1 := addr.sockaddr(c.fd.family)
- if err1 != nil {
- return 0, &OpError{Op: "write", Net: "udp", Addr: addr, Err: err1}
+ if c.fd.isConnected {
+ return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+ }
+ sa, err := addr.sockaddr(c.fd.family)
+ if err != nil {
+ return 0, &OpError{"write", c.fd.net, addr, err}
}
return c.fd.WriteTo(b, sa)
}
// WriteTo implements the net.PacketConn WriteTo method.
-func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
if !c.ok() {
return 0, os.EINVAL
}
a, ok := addr.(*UDPAddr)
if !ok {
- return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+ return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
}
return c.WriteToUDP(b, a)
}
@@ -211,7 +217,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
return nil, UnknownNetworkError(net)
}
if raddr == nil {
- return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+ return nil, &OpError{"dial", net, nil, errMissingAddress}
}
fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
if e != nil {
@@ -224,18 +230,18 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
// local address laddr. The returned connection c's ReadFrom
// and WriteTo methods can be used to receive and send UDP
// packets with per-packet addressing.
-func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
+func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
switch net {
case "udp", "udp4", "udp6":
default:
return nil, UnknownNetworkError(net)
}
if laddr == nil {
- return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+ return nil, &OpError{"listen", net, nil, errMissingAddress}
}
- fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
- if e != nil {
- return nil, e
+ fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+ if err != nil {
+ return nil, err
}
return newUDPConn(fd), nil
}
@@ -275,7 +281,7 @@ func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error {
func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := joinIPv4Group(c.fd, ifi, ip)
if err != nil {
- return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
+ return &OpError{"joinipv4group", c.fd.net, &IPAddr{ip}, err}
}
return nil
}
@@ -283,7 +289,7 @@ func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := leaveIPv4Group(c.fd, ifi, ip)
if err != nil {
- return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
+ return &OpError{"leaveipv4group", c.fd.net, &IPAddr{ip}, err}
}
return nil
}
@@ -291,7 +297,7 @@ func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := joinIPv6Group(c.fd, ifi, ip)
if err != nil {
- return &OpError{"joinipv6group", "udp", &IPAddr{ip}, err}
+ return &OpError{"joinipv6group", c.fd.net, &IPAddr{ip}, err}
}
return nil
}
@@ -299,7 +305,7 @@ func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
err := leaveIPv6Group(c.fd, ifi, ip)
if err != nil {
- return &OpError{"leaveipv6group", "udp", &IPAddr{ip}, err}
+ return &OpError{"leaveipv6group", c.fd.net, &IPAddr{ip}, err}
}
return nil
}
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 5b8b2e4c7c6..e500ddb4e0f 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -259,7 +259,7 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
}
a, ok := addr.(*UnixAddr)
if !ok {
- return 0, &OpError{"writeto", "unix", addr, os.EINVAL}
+ return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
}
return c.WriteToUnix(b, a)
}
@@ -330,7 +330,7 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
err = syscall.Listen(fd.sysfd, listenerBacklog)
if err != nil {
closesocket(fd.sysfd)
- return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: err}
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
return &UnixListener{fd, laddr.Name}, nil
}
@@ -412,7 +412,7 @@ func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err error) {
return nil, UnknownNetworkError(net)
}
if laddr == nil {
- return nil, &OpError{"listen", "unixgram", nil, errMissingAddress}
+ return nil, &OpError{"listen", net, nil, errMissingAddress}
}
fd, e := unixSocket(net, laddr, nil, "listen")
if e != nil {
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
index aa8f3934577..7d136eb3686 100644
--- a/libgo/go/os/file_plan9.go
+++ b/libgo/go/os/file_plan9.go
@@ -7,6 +7,7 @@ package os
import (
"runtime"
"syscall"
+ "time"
)
// File represents an open file descriptor.
@@ -56,12 +57,27 @@ func epipecheck(file *File, e error) {
// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
const DevNull = "/dev/null"
+// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
+func syscallMode(i FileMode) (o uint32) {
+ o |= uint32(i.Perm())
+ if i&ModeAppend != 0 {
+ o |= syscall.DMAPPEND
+ }
+ if i&ModeExclusive != 0 {
+ o |= syscall.DMEXCL
+ }
+ if i&ModeTemporary != 0 {
+ o |= syscall.DMTMP
+ }
+ return
+}
+
// OpenFile is the generalized open call; most users will use Open
// or Create instead. It opens the named file with specified flag
// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
// methods on the returned File can be used for I/O.
// It returns the File and an error, if any.
-func OpenFile(name string, flag int, perm uint32) (file *File, err error) {
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
var (
fd int
e error
@@ -89,12 +105,12 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err error) {
syscall.ForkLock.RLock()
if (create && trunc) || excl {
- fd, e = syscall.Create(name, flag, perm)
+ fd, e = syscall.Create(name, flag, syscallMode(perm))
} else {
fd, e = syscall.Open(name, flag)
if e != nil && create {
var e1 error
- fd, e1 = syscall.Create(name, flag, perm)
+ fd, e1 = syscall.Create(name, flag, syscallMode(perm))
if e1 == nil {
e = nil
}
@@ -162,18 +178,18 @@ func (f *File) Truncate(size int64) error {
return nil
}
+const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
+
// Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) error {
+func (f *File) Chmod(mode FileMode) error {
var d Dir
- var mask = ^uint32(0777)
- d.Null()
odir, e := dirstat(f)
if e != nil {
return &PathError{"chmod", f.name, e}
}
-
- d.Mode = (odir.Mode & mask) | (mode &^ mask)
+ d.Null()
+ d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
return &PathError{"chmod", f.name, e}
}
@@ -266,17 +282,15 @@ func Rename(oldname, newname string) error {
}
// Chmod changes the mode of the named file to mode.
-func Chmod(name string, mode uint32) error {
+func Chmod(name string, mode FileMode) error {
var d Dir
- var mask = ^uint32(0777)
- d.Null()
odir, e := dirstat(name)
if e != nil {
return &PathError{"chmod", name, e}
}
-
- d.Mode = (odir.Mode & mask) | (mode &^ mask)
+ d.Null()
+ d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
return &PathError{"chmod", name, e}
}
@@ -286,15 +300,14 @@ func Chmod(name string, mode uint32) error {
// Chtimes changes the access and modification times of the named
// file, similar to the Unix utime() or utimes() functions.
//
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atimeNs int64, mtimeNs int64) error {
+// The underlying filesystem may truncate or round the values to a
+// less precise time unit.
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
var d Dir
d.Null()
- d.Atime = uint32(atimeNs / 1e9)
- d.Mtime = uint32(mtimeNs / 1e9)
+ d.Atime = uint32(atime.Unix())
+ d.Mtime = uint32(mtime.Unix())
if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
return &PathError{"chtimes", name, e}
diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go
index 8d3b8a84d5c..f731e43740a 100644
--- a/libgo/go/os/stat_plan9.go
+++ b/libgo/go/os/stat_plan9.go
@@ -97,3 +97,8 @@ func Stat(name string) (FileInfo, error) {
func Lstat(name string) (FileInfo, error) {
return Stat(name)
}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+ return time.Unix(int64(fi.(*FileStat).Sys.(*Dir).Atime), 0)
+}
diff --git a/libgo/go/os/user/lookup_stubs.go b/libgo/go/os/user/lookup_stubs.go
index 42fa557445f..10f5170a9c9 100644
--- a/libgo/go/os/user/lookup_stubs.go
+++ b/libgo/go/os/user/lookup_stubs.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nocgo windows
+// +build !cgo windows
package user
diff --git a/libgo/go/patch/apply.go b/libgo/go/patch/apply.go
deleted file mode 100644
index 7c4f4ada414..00000000000
--- a/libgo/go/patch/apply.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-import "os"
-
-// An Op is a single operation to execute to apply a patch.
-type Op struct {
- Verb Verb // action
- Src string // source file
- Dst string // destination file
- Mode int // mode for destination (if non-zero)
- Data []byte // data for destination (if non-nil)
-}
-
-// Apply applies the patch set to the files named in the patch set,
-// constructing an in-memory copy of the new file state.
-// It is the client's job to write the changes to the file system
-// if desired.
-//
-// The function readFile should return the contents of the named file.
-// Typically this function will be io.ReadFile.
-//
-func (set *Set) Apply(readFile func(string) ([]byte, error)) ([]Op, error) {
- op := make([]Op, len(set.File))
-
- for i, f := range set.File {
- o := &op[i]
- o.Verb = f.Verb
- o.Src = f.Src
- o.Dst = f.Dst
- o.Mode = f.NewMode
- if f.Diff != NoDiff || o.Verb != Edit {
- // Clients assume o.Data == nil means no data diff.
- // Start with a non-nil data.
- var old []byte = make([]byte, 0) // not nil
- var err error
- if f.Src != "" {
- old, err = readFile(f.Src)
- if err != nil {
- return nil, &os.PathError{string(f.Verb), f.Src, err}
- }
- }
- o.Data, err = f.Diff.Apply(old)
- if err != nil {
- return nil, &os.PathError{string(f.Verb), f.Src, err}
- }
- }
- }
-
- return op, nil
-}
diff --git a/libgo/go/patch/git.go b/libgo/go/patch/git.go
deleted file mode 100644
index 5c233fbaebf..00000000000
--- a/libgo/go/patch/git.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-import (
- "bytes"
- "compress/zlib"
- "crypto/sha1"
- "encoding/git85"
- "errors"
- "fmt"
- "io"
-)
-
-func gitSHA1(data []byte) []byte {
- if len(data) == 0 {
- // special case: 0 length is all zeros sum
- return make([]byte, 20)
- }
- h := sha1.New()
- fmt.Fprintf(h, "blob %d\x00", len(data))
- h.Write(data)
- return h.Sum(nil)
-}
-
-// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
-
-// GitBinaryLiteral represents a Git binary literal diff.
-type GitBinaryLiteral struct {
- OldSHA1 []byte // if non-empty, the SHA1 hash of the original
- New []byte // the new contents
-}
-
-// Apply implements the Diff interface's Apply method.
-func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, error) {
- if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
- return nil, ErrPatchFailure
- }
- return d.New, nil
-}
-
-func unhex(c byte) uint8 {
- switch {
- case '0' <= c && c <= '9':
- return c - '0'
- case 'a' <= c && c <= 'f':
- return c - 'a' + 10
- case 'A' <= c && c <= 'F':
- return c - 'A' + 10
- }
- return 255
-}
-
-func getHex(s []byte) (data []byte, rest []byte) {
- n := 0
- for n < len(s) && unhex(s[n]) != 255 {
- n++
- }
- n &^= 1 // Only take an even number of hex digits.
- data = make([]byte, n/2)
- for i := range data {
- data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
- }
- rest = s[n:]
- return
-}
-
-// ParseGitBinary parses raw as a Git binary patch.
-func ParseGitBinary(raw []byte) (Diff, error) {
- var oldSHA1, newSHA1 []byte
- var sawBinary bool
-
- for {
- var first []byte
- first, raw, _ = getLine(raw, 1)
- first = bytes.TrimSpace(first)
- if s, ok := skip(first, "index "); ok {
- oldSHA1, s = getHex(s)
- if s, ok = skip(s, ".."); !ok {
- continue
- }
- newSHA1, s = getHex(s)
- continue
- }
- if _, ok := skip(first, "GIT binary patch"); ok {
- sawBinary = true
- continue
- }
- if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
- data := make([]byte, n)
- d := git85.NewDecoder(bytes.NewBuffer(raw))
- z, err := zlib.NewReader(d)
- if err != nil {
- return nil, err
- }
- defer z.Close()
- if _, err = io.ReadFull(z, data); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return nil, err
- }
- var buf [1]byte
- m, err := z.Read(buf[0:])
- if m != 0 || err != io.EOF {
- return nil, errors.New("Git binary literal longer than expected")
- }
-
- if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
- return nil, errors.New("Git binary literal SHA1 mismatch")
- }
- return &GitBinaryLiteral{oldSHA1, data}, nil
- }
- if !sawBinary {
- return nil, errors.New("unexpected Git patch header: " + string(first))
- }
- }
- panic("unreachable")
-}
diff --git a/libgo/go/patch/patch.go b/libgo/go/patch/patch.go
deleted file mode 100644
index 1d804f3362e..00000000000
--- a/libgo/go/patch/patch.go
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package patch implements parsing and execution of the textual and
-// binary patch descriptions used by version control tools such as
-// CVS, Git, Mercurial, and Subversion.
-package patch
-
-import (
- "bytes"
- "path"
- "strings"
-)
-
-// A Set represents a set of patches to be applied as a single atomic unit.
-// Patch sets are often preceded by a descriptive header.
-type Set struct {
- Header string // free-form text
- File []*File
-}
-
-// A File represents a collection of changes to be made to a single file.
-type File struct {
- Verb Verb
- Src string // source for Verb == Copy, Verb == Rename
- Dst string
- OldMode, NewMode int // 0 indicates not used
- Diff // changes to data; == NoDiff if operation does not edit file
-}
-
-// A Verb is an action performed on a file.
-type Verb string
-
-const (
- Add Verb = "add"
- Copy Verb = "copy"
- Delete Verb = "delete"
- Edit Verb = "edit"
- Rename Verb = "rename"
-)
-
-// A Diff is any object that describes changes to transform
-// an old byte stream to a new one.
-type Diff interface {
- // Apply applies the changes listed in the diff
- // to the string s, returning the new version of the string.
- // Note that the string s need not be a text string.
- Apply(old []byte) (new []byte, err error)
-}
-
-// NoDiff is a no-op Diff implementation: it passes the
-// old data through unchanged.
-var NoDiff Diff = noDiffType(0)
-
-type noDiffType int
-
-func (noDiffType) Apply(old []byte) ([]byte, error) {
- return old, nil
-}
-
-// A SyntaxError represents a syntax error encountered while parsing a patch.
-type SyntaxError string
-
-func (e SyntaxError) Error() string { return string(e) }
-
-var newline = []byte{'\n'}
-
-// Parse patches the patch text to create a patch Set.
-// The patch text typically comprises a textual header and a sequence
-// of file patches, as would be generated by CVS, Subversion,
-// Mercurial, or Git.
-func Parse(text []byte) (*Set, error) {
- // Split text into files.
- // CVS and Subversion begin new files with
- // Index: file name.
- // ==================
- // diff -u blah blah
- //
- // Mercurial and Git use
- // diff [--git] a/file/path b/file/path.
- //
- // First look for Index: lines. If none, fall back on diff lines.
- text, files := sections(text, "Index: ")
- if len(files) == 0 {
- text, files = sections(text, "diff ")
- }
-
- set := &Set{string(text), make([]*File, len(files))}
-
- // Parse file header and then
- // parse files into patch chunks.
- // Each chunk begins with @@.
- for i, raw := range files {
- p := new(File)
- set.File[i] = p
-
- // First line of hdr is the Index: that
- // begins the section. After that is the file name.
- s, raw, _ := getLine(raw, 1)
- if hasPrefix(s, "Index: ") {
- p.Dst = string(bytes.TrimSpace(s[7:]))
- goto HaveName
- } else if hasPrefix(s, "diff ") {
- str := string(bytes.TrimSpace(s))
- i := strings.LastIndex(str, " b/")
- if i >= 0 {
- p.Dst = str[i+3:]
- goto HaveName
- }
- }
- return nil, SyntaxError("unexpected patch header line: " + string(s))
- HaveName:
- p.Dst = path.Clean(p.Dst)
- if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
- return nil, SyntaxError("invalid path: " + p.Dst)
- }
-
- // Parse header lines giving file information:
- // new file mode %o - file created
- // deleted file mode %o - file deleted
- // old file mode %o - file mode changed
- // new file mode %o - file mode changed
- // rename from %s - file renamed from other file
- // rename to %s
- // copy from %s - file copied from other file
- // copy to %s
- p.Verb = Edit
- for len(raw) > 0 {
- oldraw := raw
- var l []byte
- l, raw, _ = getLine(raw, 1)
- l = bytes.TrimSpace(l)
- if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
- p.NewMode = m
- p.Verb = Add
- continue
- }
- if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
- p.OldMode = m
- p.Verb = Delete
- p.Src = p.Dst
- p.Dst = ""
- continue
- }
- if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
- // usually implies p.Verb = "rename" or "copy"
- // but we'll get that from the rename or copy line.
- p.OldMode = m
- continue
- }
- if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
- p.OldMode = m
- continue
- }
- if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
- p.NewMode = m
- continue
- }
- if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
- p.Src = string(s)
- p.Verb = Rename
- continue
- }
- if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
- p.Verb = Rename
- continue
- }
- if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
- p.Src = string(s)
- p.Verb = Copy
- continue
- }
- if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
- p.Verb = Copy
- continue
- }
- if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
- // Hg prints
- // Binary file foo has changed
- // when deleting a binary file.
- continue
- }
- if s, ok := skip(l, "RCS file: "); ok && len(s) > 0 {
- // CVS prints
- // RCS file: /cvs/plan9/bin/yesterday,v
- // retrieving revision 1.1
- // for each file.
- continue
- }
- if s, ok := skip(l, "retrieving revision "); ok && len(s) > 0 {
- // CVS prints
- // RCS file: /cvs/plan9/bin/yesterday,v
- // retrieving revision 1.1
- // for each file.
- continue
- }
- if hasPrefix(l, "===") || hasPrefix(l, "---") || hasPrefix(l, "+++") || hasPrefix(l, "diff ") {
- continue
- }
- if hasPrefix(l, "@@ -") {
- diff, err := ParseTextDiff(oldraw)
- if err != nil {
- return nil, err
- }
- p.Diff = diff
- break
- }
- if hasPrefix(l, "GIT binary patch") || (hasPrefix(l, "index ") && !hasPrefix(raw, "--- ")) {
- diff, err := ParseGitBinary(oldraw)
- if err != nil {
- return nil, err
- }
- p.Diff = diff
- break
- }
- if hasPrefix(l, "index ") {
- continue
- }
- return nil, SyntaxError("unexpected patch header line: " + string(l))
- }
- if p.Diff == nil {
- p.Diff = NoDiff
- }
- if p.Verb == Edit {
- p.Src = p.Dst
- }
- }
-
- return set, nil
-}
-
-// getLine returns the first n lines of data and the remainder.
-// If data has no newline, getLine returns data, nil, false
-func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
- rest = data
- ok = true
- for ; n > 0; n-- {
- nl := bytes.Index(rest, newline)
- if nl < 0 {
- rest = nil
- ok = false
- break
- }
- rest = rest[nl+1:]
- }
- first = data[0 : len(data)-len(rest)]
- return
-}
-
-// sections returns a collection of file sections,
-// each of which begins with a line satisfying prefix.
-// text before the first instance of such a line is
-// returned separately.
-func sections(text []byte, prefix string) ([]byte, [][]byte) {
- n := 0
- for b := text; ; {
- if hasPrefix(b, prefix) {
- n++
- }
- nl := bytes.Index(b, newline)
- if nl < 0 {
- break
- }
- b = b[nl+1:]
- }
-
- sect := make([][]byte, n+1)
- n = 0
- for b := text; ; {
- if hasPrefix(b, prefix) {
- sect[n] = text[0 : len(text)-len(b)]
- n++
- text = b
- }
- nl := bytes.Index(b, newline)
- if nl < 0 {
- sect[n] = text
- break
- }
- b = b[nl+1:]
- }
- return sect[0], sect[1:]
-}
-
-// if s begins with the prefix t, skip returns
-// s with that prefix removed and ok == true.
-func skip(s []byte, t string) (ss []byte, ok bool) {
- if len(s) < len(t) || string(s[0:len(t)]) != t {
- return nil, false
- }
- return s[len(t):], true
-}
-
-// if s begins with the prefix t and then is a sequence
-// of digits in the given base, atoi returns the number
-// represented by the digits and s with the
-// prefix and the digits removed.
-func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
- if s, ok = skip(s, t); !ok {
- return
- }
- var i int
- for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
- n = n*base + int(s[i]-'0')
- }
- if i == 0 {
- return
- }
- return n, s[i:], true
-}
-
-// hasPrefix returns true if s begins with t.
-func hasPrefix(s []byte, t string) bool {
- _, ok := skip(s, t)
- return ok
-}
-
-// splitLines returns the result of splitting s into lines.
-// The \n on each line is preserved.
-func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline) }
diff --git a/libgo/go/patch/patch_test.go b/libgo/go/patch/patch_test.go
deleted file mode 100644
index 0a4aef7ea62..00000000000
--- a/libgo/go/patch/patch_test.go
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-// TODO(rsc): test Apply
-
-import "testing"
-
-type Test struct {
- in string
- out string
- diff string
-}
-
-func TestFileApply(t *testing.T) {
- for i, test := range tests {
- set, err := Parse([]byte(test.diff))
- if err != nil {
- t.Errorf("#%d: Parse: %s", i, err)
- continue
- }
- if len(set.File) != 1 {
- t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File))
- continue
- }
- new, err := set.File[0].Apply([]byte(test.in))
- if err != nil {
- t.Errorf("#%d: Apply: %s", i, err)
- continue
- }
- if s := string(new); s != test.out {
- t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)
- }
- }
-}
-
-var tests = []Test{
- {
- "hello, world\n",
- "goodbye, world\n",
- "Index: a\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1 +1 @@\n" +
- "-hello, world\n" +
- "+goodbye, world\n",
- },
- {
- "hello, world\n",
- "goodbye, world\n",
- "Index: a\n" +
- "index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1 +1 @@\n" +
- "-hello, world\n" +
- "+goodbye, world\n",
- },
- {
- "hello, world\n",
- "goodbye, world\n",
- "diff a/a b/b\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1,1 +1,1 @@\n" +
- "-hello, world\n" +
- "+goodbye, world\n",
- },
- {
- "hello, world",
- "goodbye, world\n",
- "diff --git a/a b/b\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1 +1 @@\n" +
- "-hello, world\n" +
- "\\ No newline at end of file\n" +
- "+goodbye, world\n",
- },
- {
- "hello, world\n",
- "goodbye, world",
- "Index: a\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1 +1 @@\n" +
- "-hello, world\n" +
- "+goodbye, world\n" +
- "\\ No newline at end of file\n",
- },
- {
- "hello, world",
- "goodbye, world",
- "Index: a\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1 +1 @@\n" +
- "-hello, world\n" +
- "\\ No newline at end of file\n" +
- "+goodbye, world\n" +
- "\\ No newline at end of file\n",
- },
- {
- "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\n",
- "a\nB\nC\nD\ne\nf\ng\nj\nk\nl\nm\nN\n",
- "Index: a\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1,14 +1,12 @@\n" +
- " a\n" +
- "-b\n" +
- "-c\n" +
- "-d\n" +
- "+B\n" +
- "+C\n" +
- "+D\n" +
- " e\n" +
- " f\n" +
- " g\n" +
- "-h\n" +
- "-i\n" +
- " j\n" +
- " k\n" +
- " l\n" +
- " m\n" +
- "-n\n" +
- "+N\n",
- },
- {
- "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
- "a\nb\nc\ng\nh\ni\nj\nk\nl\nm\nN\nO\np\nq\nr\ns\nt\nu\nv\nw\nd\ne\nf\nx\n",
- "Index: a\n" +
- "--- a/a\n" +
- "+++ b/b\n" +
- "@@ -1,9 +1,6 @@\n" +
- " a\n" +
- " b\n" +
- " c\n" +
- "-d\n" +
- "-e\n" +
- "-f\n" +
- " g\n" +
- " h\n" +
- " i\n" +
- "@@ -11,8 +8,8 @@ j\n" +
- " k\n" +
- " l\n" +
- " m\n" +
- "-n\n" +
- "-o\n" +
- "+N\n" +
- "+O\n" +
- " p\n" +
- " q\n" +
- " r\n" +
- "\n" +
- "@@ -21,6 +18,7 @@ t\n" +
- " u\n" +
- " v\n" +
- " w\n" +
- "+d\n" +
- "+e\n" +
- "+f\n" +
- " x\n" +
- "-y\n" +
- "-z\n",
- },
- {
- "a\nb\nc\ng\nh\ni\nj\nk\nl\nm\nN\nO\np\nq\nr\ns\nt\nu\nv\nw\nd\ne\nf\nx\n",
- "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
- "Index: a\n" +
- "--- a/b\n" +
- "+++ b/a\n" +
- "@@ -1,6 +1,9 @@\n" +
- " a\n" +
- " b\n" +
- " c\n" +
- "+d\n" +
- "+e\n" +
- "+f\n" +
- " g\n" +
- " h\n" +
- " i\n" +
- "@@ -8,8 +11,8 @@ j\n" +
- " k\n" +
- " l\n" +
- " m\n" +
- "-N\n" +
- "-O\n" +
- "+n\n" +
- "+o\n" +
- " p\n" +
- " q\n" +
- " r\n" +
- "@@ -18,7 +21,6 @@ t\n" +
- " u\n" +
- " v\n" +
- " w\n" +
- "-d\n" +
- "-e\n" +
- "-f\n" +
- " x\n" +
- "+y\n" +
- "+z\n",
- },
- {
- "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
- "",
- "Index: a\n" +
- "deleted file mode 100644\n" +
- "--- a/a\n" +
- "+++ /dev/null\n" +
- "@@ -1,26 +0,0 @@\n" +
- "-a\n" +
- "-b\n" +
- "-c\n" +
- "-d\n" +
- "-e\n" +
- "-f\n" +
- "-g\n" +
- "-h\n" +
- "-i\n" +
- "-j\n" +
- "-k\n" +
- "-l\n" +
- "-m\n" +
- "-n\n" +
- "-o\n" +
- "-p\n" +
- "-q\n" +
- "-r\n" +
- "-s\n" +
- "-t\n" +
- "-u\n" +
- "-v\n" +
- "-w\n" +
- "-x\n" +
- "-y\n" +
- "-z\n",
- },
- {
- "",
- "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
- "Index: a\n" +
- "new file mode 100644\n" +
- "--- /dev/null\n" +
- "+++ b/a\n" +
- "@@ -0,0 +1,26 @@\n" +
- "+a\n" +
- "+b\n" +
- "+c\n" +
- "+d\n" +
- "+e\n" +
- "+f\n" +
- "+g\n" +
- "+h\n" +
- "+i\n" +
- "+j\n" +
- "+k\n" +
- "+l\n" +
- "+m\n" +
- "+n\n" +
- "+o\n" +
- "+p\n" +
- "+q\n" +
- "+r\n" +
- "+s\n" +
- "+t\n" +
- "+u\n" +
- "+v\n" +
- "+w\n" +
- "+x\n" +
- "+y\n" +
- "+z\n",
- },
- {
- "\xc2\xd8\xf9\x63\x8c\xf7\xc6\x9b\xb0\x3c\x39\xfa\x08\x8e\x42\x8f" +
- "\x1c\x7c\xaf\x54\x22\x87\xc3\xc5\x68\x9b\xe1\xbd\xbc\xc3\xe0\xda" +
- "\xcc\xe3\x96\xda\xc2\xaf\xbb\x75\x79\x64\x86\x60\x8a\x43\x9e\x07" +
- "\x9c\xaa\x92\x88\xd4\x30\xb9\x8b\x95\x04\x60\x71\xc7\xbb\x2d\x93" +
- "\x66\x73\x01\x24\xf3\x63\xbf\xe6\x1d\x38\x15\x56\x98\xc4\x1f\x85" +
- "\xc3\x60\x39\x3a\x0d\x57\x53\x0c\x29\x3f\xbb\x44\x7e\x56\x56\x9d" +
- "\x87\xcf\xf6\x88\xe8\x98\x05\x85\xf8\xfe\x44\x21\xfa\x33\xc9\xa4" +
- "\x22\xbe\x89\x05\x8b\x82\x76\xc9\x7c\xaf\x48\x28\xc4\x86\x15\x89" +
- "\xb9\x98\xfa\x41\xfc\x3d\x8d\x80\x29\x33\x17\x45\xa5\x7f\x67\x79" +
- "\x7f\x92\x3b\x2e\x4c\xc1\xd2\x1b\x9e\xcf\xed\x53\x56\xb2\x49\x58" +
- "\xd8\xe9\x9f\x98\xa3\xfe\x78\xe1\xe8\x74\x71\x04\x1a\x87\xd9\x68" +
- "\x18\x68\xd0\xae\x7b\xa4\x25\xe3\x06\x03\x7e\x8b\xd3\x50\x1f\xb1" +
- "\x67\x08\xe3\x93\xf4\x4f\xa1\xfb\x31\xcf\x99\x5a\x43\x9f\x4b\xc4" +
- "\xaa\x68\x1a\xf9\x8e\x97\x02\x80\x17\xf1\x25\x21\xdf\x94\xbf\x41" +
- "\x08\x59\x3d\xea\x36\x23\x03\xb5\x62\x4d\xb6\x8f\x9e\xdf\x1f\x03" +
- "\x7d\x70\xe0\x6f\x46\x08\x96\x79\x72\xb7\xae\x41\x2b\xbd\x2a\x95",
-
- "\x8e\x5f\xf8\x79\x36\x8d\xbe\x68\xc4\x2c\x78\x8a\x46\x28\x40\x3e" +
- "\xcf\x3b\xb9\x14\xaf\xfa\x04\x9e\x4b\xa2\x52\x51\x51\xf0\xad\xd3" +
- "\x03\x1c\x03\x79\x5f\x53\xc7\x1a\xd5\x28\xe2\xd9\x19\x37\xa4\xfa" +
- "\xdd\xff\xac\xb5\xa9\x42\x4e\x17\xeb\xb4\x0d\x20\x67\x08\x43\x21" +
- "\x7d\x12\x27\xfa\x96\x7a\x85\xf8\x04\x5f\xf4\xfe\xda\x9f\x66\xf2" +
- "\xba\x04\x39\x00\xab\x3f\x23\x20\x84\x53\xb4\x88\xb6\xee\xa2\x9e" +
- "\xc1\xca\xd4\x09\x2a\x27\x89\x2f\xcb\xba\xa6\x41\xb6\xe9\xc5\x08" +
- "\xff\xf5\x95\x35\xab\xbb\x5c\x62\x96\xe7\x7c\x8f\xf2\x40\x12\xc9" +
- "\x2d\xfe\xff\x75\x4f\x70\x47\xc9\xcd\x15\x0a\x1c\x23\xe7\x0f\x15" +
- "\x95\x75\x30\x8f\x6e\x9f\x7e\xa5\x9d\xd1\x65\x1c\x4d\x4e\xf4\x32" +
- "\x49\x9b\xa1\x30\x44\x62\x6f\xe2\xe6\x69\x09\xf8\x7c\x7c\xbe\x07" +
- "\xa9\xb6\x14\x7a\x6b\x85\xe4\xbf\x48\xbe\x5b\x3b\x70\xb3\x79\x3b" +
- "\xc4\x35\x9d\x86\xf1\xfe\x2b\x6f\x80\x74\x50\xf3\x96\x59\x53\x1a" +
- "\x75\x46\x9d\x57\x72\xb3\xb1\x26\xf5\x81\xcd\x96\x08\xbc\x2b\x10" +
- "\xdc\x80\xbd\xd0\xdf\x03\x6d\x8d\xec\x30\x2b\x4c\xdb\x4d\x3b\xef" +
- "\x7d\x3a\x39\xc8\x5a\xc4\xcc\x24\x37\xde\xe2\x95\x2b\x04\x97\xb0",
-
- // From git diff --binary
- "Index: a\n" +
- "index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f 100644\n" +
- "GIT binary patch\n" +
- "literal 256\n" +
- "zcmV+b0ssDvU-)@8jlO8aEO?4WC_p~XJGm6E`UIX!qEb;&@U7DW90Pe@Q^y+BDB{@}\n" +
- "zH>CRA|E#sCLQWU!v<)C<2ty%#5-0kWdWHA|U-bUkpJwv91UUe!KO-Q7Q?!V-?xLQ-\n" +
- "z%G3!eCy6i1x~4(4>BR{D^_4ZNyIf+H=X{UyKoZF<{{MAPa7W3_6$%_9=MNQ?buf=^\n" +
- "zpMIsC(PbP>PV_QKo1rj7VsGN+X$kmze7*;%wiJ46h2+0TzFRwRvw1tjHJyg>{wr^Q\n" +
- "zbWrn_SyLKyMx9r3v#}=ifz6f(yekmgfW6S)18t4$Fe^;kO*`*>IyuN%#LOf&-r|)j\n" +
- "G1edVN^?m&S\n" +
- "\n" +
- "literal 256\n" +
- "zcmV+b0ssEO*!g3O_r{yBJURLZjzW(de6Lg@hr`8ao8i5@!{FM?<CfaOue)`5WQJgh\n" +
- "zL!Jkms*;G*Fu9AB1YmK;yDgJua{(mtW54DdI2Bfy#2<yjU^zMsS5pirKf6SJR#u&d\n" +
- "z&-RGum<5IS{zM`AGs&bPzKI2kf_BM#uSh7wh82mqnEFBdJ&k}VGZ#gre`k4rk~=O;\n" +
- "z!O|O^&+SuIvPoFj>7SUR{&?Z&ba4b4huLTtXwa^Eq$T491AdFsP#>{p2;-CVPoeuU\n" +
- "z&zV|7pG(B5Xd3yBmjZwn@g*VOl)pg;Sv~4DBLlT!O}3Ao-yZ{gaNuu72$p$rx2{1e\n" +
- "Gy(*Pb;D3Ms\n" +
- "\n",
- },
- {
- "\xc2\xd8\xf9\x63\x8c\xf7\xc6\x9b\xb0\x3c\x39\xfa\x08\x8e\x42\x8f" +
- "\x1c\x7c\xaf\x54\x22\x87\xc3\xc5\x68\x9b\xe1\xbd\xbc\xc3\xe0\xda" +
- "\xcc\xe3\x96\xda\xc2\xaf\xbb\x75\x79\x64\x86\x60\x8a\x43\x9e\x07" +
- "\x9c\xaa\x92\x88\xd4\x30\xb9\x8b\x95\x04\x60\x71\xc7\xbb\x2d\x93" +
- "\x66\x73\x01\x24\xf3\x63\xbf\xe6\x1d\x38\x15\x56\x98\xc4\x1f\x85" +
- "\xc3\x60\x39\x3a\x0d\x57\x53\x0c\x29\x3f\xbb\x44\x7e\x56\x56\x9d" +
- "\x87\xcf\xf6\x88\xe8\x98\x05\x85\xf8\xfe\x44\x21\xfa\x33\xc9\xa4" +
- "\x22\xbe\x89\x05\x8b\x82\x76\xc9\x7c\xaf\x48\x28\xc4\x86\x15\x89" +
- "\xb9\x98\xfa\x41\xfc\x3d\x8d\x80\x29\x33\x17\x45\xa5\x7f\x67\x79" +
- "\x7f\x92\x3b\x2e\x4c\xc1\xd2\x1b\x9e\xcf\xed\x53\x56\xb2\x49\x58" +
- "\xd8\xe9\x9f\x98\xa3\xfe\x78\xe1\xe8\x74\x71\x04\x1a\x87\xd9\x68" +
- "\x18\x68\xd0\xae\x7b\xa4\x25\xe3\x06\x03\x7e\x8b\xd3\x50\x1f\xb1" +
- "\x67\x08\xe3\x93\xf4\x4f\xa1\xfb\x31\xcf\x99\x5a\x43\x9f\x4b\xc4" +
- "\xaa\x68\x1a\xf9\x8e\x97\x02\x80\x17\xf1\x25\x21\xdf\x94\xbf\x41" +
- "\x08\x59\x3d\xea\x36\x23\x03\xb5\x62\x4d\xb6\x8f\x9e\xdf\x1f\x03" +
- "\x7d\x70\xe0\x6f\x46\x08\x96\x79\x72\xb7\xae\x41\x2b\xbd\x2a\x95",
-
- "\x8e\x5f\xf8\x79\x36\x8d\xbe\x68\xc4\x2c\x78\x8a\x46\x28\x40\x3e" +
- "\xcf\x3b\xb9\x14\xaf\xfa\x04\x9e\x4b\xa2\x52\x51\x51\xf0\xad\xd3" +
- "\x03\x1c\x03\x79\x5f\x53\xc7\x1a\xd5\x28\xe2\xd9\x19\x37\xa4\xfa" +
- "\xdd\xff\xac\xb5\xa9\x42\x4e\x17\xeb\xb4\x0d\x20\x67\x08\x43\x21" +
- "\x7d\x12\x27\xfa\x96\x7a\x85\xf8\x04\x5f\xf4\xfe\xda\x9f\x66\xf2" +
- "\xba\x04\x39\x00\xab\x3f\x23\x20\x84\x53\xb4\x88\xb6\xee\xa2\x9e" +
- "\xc1\xca\xd4\x09\x2a\x27\x89\x2f\xcb\xba\xa6\x41\xb6\xe9\xc5\x08" +
- "\xff\xf5\x95\x35\xab\xbb\x5c\x62\x96\xe7\x7c\x8f\xf2\x40\x12\xc9" +
- "\x2d\xfe\xff\x75\x4f\x70\x47\xc9\xcd\x15\x0a\x1c\x23\xe7\x0f\x15" +
- "\x95\x75\x30\x8f\x6e\x9f\x7e\xa5\x9d\xd1\x65\x1c\x4d\x4e\xf4\x32" +
- "\x49\x9b\xa1\x30\x44\x62\x6f\xe2\xe6\x69\x09\xf8\x7c\x7c\xbe\x07" +
- "\xa9\xb6\x14\x7a\x6b\x85\xe4\xbf\x48\xbe\x5b\x3b\x70\xb3\x79\x3b" +
- "\xc4\x35\x9d\x86\xf1\xfe\x2b\x6f\x80\x74\x50\xf3\x96\x59\x53\x1a" +
- "\x75\x46\x9d\x57\x72\xb3\xb1\x26\xf5\x81\xcd\x96\x08\xbc\x2b\x10" +
- "\xdc\x80\xbd\xd0\xdf\x03\x6d\x8d\xec\x30\x2b\x4c\xdb\x4d\x3b\xef" +
- "\x7d\x3a\x39\xc8\x5a\xc4\xcc\x24\x37\xde\xe2\x95\x2b\x04\x97\xb0",
-
- // From hg diff --git
- "Index: a\n" +
- "index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f\n" +
- "GIT binary patch\n" +
- "literal 256\n" +
- "zc$@(M0ssDvU-)@8jlO8aEO?4WC_p~XJGm6E`UIX!qEb;&@U7DW90Pe@Q^y+BDB{@}\n" +
- "zH>CRA|E#sCLQWU!v<)C<2ty%#5-0kWdWHA|U-bUkpJwv91UUe!KO-Q7Q?!V-?xLQ-\n" +
- "z%G3!eCy6i1x~4(4>BR{D^_4ZNyIf+H=X{UyKoZF<{{MAPa7W3_6$%_9=MNQ?buf=^\n" +
- "zpMIsC(PbP>PV_QKo1rj7VsGN+X$kmze7*;%wiJ46h2+0TzFRwRvw1tjHJyg>{wr^Q\n" +
- "zbWrn_SyLKyMx9r3v#}=ifz6f(yekmgfW6S)18t4$Fe^;kO*`*>IyuN%#LOf&-r|)j\n" +
- "G1edVN^?m&S\n" +
- "\n",
- },
- {
- "",
- "",
- "Index: hello\n" +
- "===================================================================\n" +
- "old mode 100644\n" +
- "new mode 100755\n",
- },
-}
diff --git a/libgo/go/patch/textdiff.go b/libgo/go/patch/textdiff.go
deleted file mode 100644
index c9cffee11c4..00000000000
--- a/libgo/go/patch/textdiff.go
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-import (
- "bytes"
- "errors"
-)
-
-type TextDiff []TextChunk
-
-// A TextChunk specifies an edit to a section of a file:
-// the text beginning at Line, which should be exactly Old,
-// is to be replaced with New.
-type TextChunk struct {
- Line int
- Old []byte
- New []byte
-}
-
-func ParseTextDiff(raw []byte) (TextDiff, error) {
- var chunkHeader []byte
-
- // Copy raw so it is safe to keep references to slices.
- _, chunks := sections(raw, "@@ -")
- delta := 0
- diff := make(TextDiff, len(chunks))
- for i, raw := range chunks {
- c := &diff[i]
-
- // Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
- chunk := splitLines(raw)
- chunkHeader = chunk[0]
- var ok bool
- var oldLine, oldCount, newLine, newCount int
- s := chunkHeader
- if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
- goto ErrChunkHdr
- }
- if len(s) == 0 || s[0] != ',' {
- oldCount = 1
- } else if oldCount, s, ok = atoi(s, ",", 10); !ok {
- goto ErrChunkHdr
- }
- if newLine, s, ok = atoi(s, " +", 10); !ok {
- goto ErrChunkHdr
- }
- if len(s) == 0 || s[0] != ',' {
- newCount = 1
- } else if newCount, s, ok = atoi(s, ",", 10); !ok {
- goto ErrChunkHdr
- }
- if !hasPrefix(s, " @@") {
- goto ErrChunkHdr
- }
-
- // Special case: for created or deleted files, the empty half
- // is given as starting at line 0. Translate to line 1.
- if oldCount == 0 && oldLine == 0 {
- oldLine = 1
- }
- if newCount == 0 && newLine == 0 {
- newLine = 1
- }
-
- // Count lines in text
- var dropOldNL, dropNewNL bool
- var nold, nnew int
- var lastch byte
- chunk = chunk[1:]
- for _, l := range chunk {
- if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
- if len(bytes.TrimSpace(l)) != 0 {
- return nil, SyntaxError("too many chunk lines")
- }
- continue
- }
- if len(l) == 0 {
- return nil, SyntaxError("empty chunk line")
- }
- switch l[0] {
- case '+':
- nnew++
- case '-':
- nold++
- case ' ':
- nnew++
- nold++
- case '\\':
- if _, ok := skip(l, "\\ No newline at end of file"); ok {
- switch lastch {
- case '-':
- dropOldNL = true
- case '+':
- dropNewNL = true
- case ' ':
- dropOldNL = true
- dropNewNL = true
- default:
- return nil, SyntaxError("message `\\ No newline at end of file' out of context")
- }
- break
- }
- fallthrough
- default:
- return nil, SyntaxError("unexpected chunk line: " + string(l))
- }
- lastch = l[0]
- }
-
- // Does it match the header?
- if nold != oldCount || nnew != newCount {
- return nil, SyntaxError("chunk header does not match line count: " + string(chunkHeader))
- }
- if oldLine+delta != newLine {
- return nil, SyntaxError("chunk delta is out of sync with previous chunks")
- }
- delta += nnew - nold
- c.Line = oldLine
-
- var old, new bytes.Buffer
- nold = 0
- nnew = 0
- for _, l := range chunk {
- if nold == oldCount && nnew == newCount {
- break
- }
- ch, l := l[0], l[1:]
- if ch == '\\' {
- continue
- }
- if ch != '+' {
- old.Write(l)
- nold++
- }
- if ch != '-' {
- new.Write(l)
- nnew++
- }
- }
- c.Old = old.Bytes()
- c.New = new.Bytes()
- if dropOldNL {
- c.Old = c.Old[0 : len(c.Old)-1]
- }
- if dropNewNL {
- c.New = c.New[0 : len(c.New)-1]
- }
- }
- return diff, nil
-
-ErrChunkHdr:
- return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
-}
-
-var ErrPatchFailure = errors.New("patch did not apply cleanly")
-
-// Apply applies the changes listed in the diff
-// to the data, returning the new version.
-func (d TextDiff) Apply(data []byte) ([]byte, error) {
- var buf bytes.Buffer
- line := 1
- for _, c := range d {
- var ok bool
- var prefix []byte
- prefix, data, ok = getLine(data, c.Line-line)
- if !ok || !bytes.HasPrefix(data, c.Old) {
- return nil, ErrPatchFailure
- }
- buf.Write(prefix)
- data = data[len(c.Old):]
- buf.Write(c.New)
- line = c.Line + bytes.Count(c.Old, newline)
- }
- buf.Write(data)
- return buf.Bytes(), nil
-}
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index 63adcb88c46..2601d183848 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -295,6 +295,7 @@ func makeTree(t *testing.T) {
fd, err := os.Create(path)
if err != nil {
t.Errorf("makeTree: %v", err)
+ return
}
fd.Close()
} else {
@@ -344,10 +345,10 @@ func TestWalk(t *testing.T) {
// Expect no errors.
err := filepath.Walk(tree.name, markFn)
if err != nil {
- t.Errorf("no error expected, found: %s", err)
+ t.Fatalf("no error expected, found: %s", err)
}
if len(errors) != 0 {
- t.Errorf("unexpected errors: %s", errors)
+ t.Fatalf("unexpected errors: %s", errors)
}
checkMarks(t, true)
errors = errors[0:0]
@@ -369,7 +370,7 @@ func TestWalk(t *testing.T) {
tree.entries[3].mark--
err := filepath.Walk(tree.name, markFn)
if err != nil {
- t.Errorf("expected no error return from Walk, %s", err)
+ t.Fatalf("expected no error return from Walk, got %s", err)
}
if len(errors) != 2 {
t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
@@ -388,7 +389,7 @@ func TestWalk(t *testing.T) {
clear = false // error will stop processing
err = filepath.Walk(tree.name, markFn)
if err == nil {
- t.Errorf("expected error return from Walk")
+ t.Fatalf("expected error return from Walk")
}
if len(errors) != 1 {
t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
@@ -660,11 +661,13 @@ func TestAbs(t *testing.T) {
info, err := os.Stat(path)
if err != nil {
t.Errorf("%s: %s", path, err)
+ continue
}
abspath, err := filepath.Abs(path)
if err != nil {
t.Errorf("Abs(%q) error: %v", path, err)
+ continue
}
absinfo, err := os.Stat(abspath)
if err != nil || !absinfo.(*os.FileStat).SameFile(info.(*os.FileStat)) {
diff --git a/libgo/go/regexp/regexp.go b/libgo/go/regexp/regexp.go
index ef94fa09b11..7aebd3728a3 100644
--- a/libgo/go/regexp/regexp.go
+++ b/libgo/go/regexp/regexp.go
@@ -66,13 +66,6 @@ import (
var debug = false
-// Error is the local type for a parsing error.
-type Error string
-
-func (e Error) Error() string {
- return string(e)
-}
-
// Regexp is the representation of a compiled regular expression.
// The public interface is entirely through methods.
// A Regexp is safe for concurrent use by multiple goroutines.
diff --git a/libgo/go/runtime/chan_test.go b/libgo/go/runtime/chan_test.go
index 7cea906ceae..eb2c7c60d0c 100644
--- a/libgo/go/runtime/chan_test.go
+++ b/libgo/go/runtime/chan_test.go
@@ -371,3 +371,12 @@ func BenchmarkChanCreation(b *testing.B) {
<-c
}
}
+
+func BenchmarkChanSem(b *testing.B) {
+ type Empty struct{}
+ c := make(chan Empty, 1)
+ for i := 0; i < b.N; i++ {
+ c <- Empty{}
+ <-c
+ }
+}
diff --git a/libgo/go/runtime/debug.go b/libgo/go/runtime/debug.go
index c2b90566a99..4f09146fac1 100644
--- a/libgo/go/runtime/debug.go
+++ b/libgo/go/runtime/debug.go
@@ -23,6 +23,9 @@ func UnlockOSThread()
// This call will go away when the scheduler improves.
func GOMAXPROCS(n int) int
+// NumCPU returns the number of logical CPUs on the local machine.
+func NumCPU() int
+
// Cgocalls returns the number of cgo calls made by the current process.
func Cgocalls() int64
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index 88598cb7d4b..eafa2f19f19 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -68,9 +68,6 @@ func funcline_go(*Func, uintptr) (string, int)
// mid returns the current os thread (m) id.
func mid() uint32
-// NumCPU returns the number of logical CPUs on the local machine.
-func NumCPU() int
-
// Semacquire waits until *s > 0 and then atomically decrements it.
// It is intended as a simple sleep primitive for use by the synchronization
// library and should not be used directly.
diff --git a/libgo/go/websocket/client.go b/libgo/go/websocket/client.go
deleted file mode 100644
index 89cdcda71ae..00000000000
--- a/libgo/go/websocket/client.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "crypto/tls"
- "io"
- "net"
- "net/url"
-)
-
-// DialError is an error that occurs while dialling a websocket server.
-type DialError struct {
- *Config
- Err error
-}
-
-func (e *DialError) Error() string {
- return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
-}
-
-// NewConfig creates a new WebSocket config for client connection.
-func NewConfig(server, origin string) (config *Config, err error) {
- config = new(Config)
- config.Version = ProtocolVersionHybi13
- config.Location, err = url.ParseRequest(server)
- if err != nil {
- return
- }
- config.Origin, err = url.ParseRequest(origin)
- if err != nil {
- return
- }
- return
-}
-
-// NewClient creates a new WebSocket client connection over rwc.
-func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
- br := bufio.NewReader(rwc)
- bw := bufio.NewWriter(rwc)
- switch config.Version {
- case ProtocolVersionHixie75:
- err = hixie75ClientHandshake(config, br, bw)
- case ProtocolVersionHixie76, ProtocolVersionHybi00:
- err = hixie76ClientHandshake(config, br, bw)
- case ProtocolVersionHybi08, ProtocolVersionHybi13:
- err = hybiClientHandshake(config, br, bw)
- default:
- err = ErrBadProtocolVersion
- }
- if err != nil {
- return
- }
- buf := bufio.NewReadWriter(br, bw)
- switch config.Version {
- case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00:
- ws = newHixieClientConn(config, buf, rwc)
- case ProtocolVersionHybi08, ProtocolVersionHybi13:
- ws = newHybiClientConn(config, buf, rwc)
- }
- return
-}
-
-/*
-Dial opens a new client connection to a WebSocket.
-
-A trivial example client:
-
- package main
-
- import (
- "log"
- "net/http"
- "strings"
- "websocket"
- )
-
- func main() {
- origin := "http://localhost/"
- url := "ws://localhost/ws"
- ws, err := websocket.Dial(url, "", origin)
- if err != nil {
- log.Fatal(err)
- }
- if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
- log.Fatal(err)
- }
- var msg = make([]byte, 512);
- if n, err := ws.Read(msg); err != nil {
- log.Fatal(err)
- }
- // use msg[0:n]
- }
-*/
-func Dial(url_, protocol, origin string) (ws *Conn, err error) {
- config, err := NewConfig(url_, origin)
- if err != nil {
- return nil, err
- }
- return DialConfig(config)
-}
-
-// DialConfig opens a new client connection to a WebSocket with a config.
-func DialConfig(config *Config) (ws *Conn, err error) {
- var client net.Conn
- if config.Location == nil {
- return nil, &DialError{config, ErrBadWebSocketLocation}
- }
- if config.Origin == nil {
- return nil, &DialError{config, ErrBadWebSocketOrigin}
- }
- switch config.Location.Scheme {
- case "ws":
- client, err = net.Dial("tcp", config.Location.Host)
-
- case "wss":
- client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
-
- default:
- err = ErrBadScheme
- }
- if err != nil {
- goto Error
- }
-
- ws, err = NewClient(config, client)
- if err != nil {
- goto Error
- }
- return
-
-Error:
- return nil, &DialError{config, err}
-}
diff --git a/libgo/go/websocket/hixie.go b/libgo/go/websocket/hixie.go
deleted file mode 100644
index 22dbc1f8db3..00000000000
--- a/libgo/go/websocket/hixie.go
+++ /dev/null
@@ -1,695 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-// This file implements a protocol of Hixie draft version 75 and 76
-// (draft 76 equals to hybi 00)
-
-import (
- "bufio"
- "bytes"
- "crypto/md5"
- "encoding/binary"
- "fmt"
- "io"
- "io/ioutil"
- "math/rand"
- "net/http"
- "net/url"
- "strconv"
- "strings"
-)
-
-// An aray of characters to be randomly inserted to construct Sec-WebSocket-Key
-// value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E.
-// See Step 21 in Section 4.1 Opening handshake.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22
-var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
-
-func init() {
- i := 0
- for ch := byte(0x21); ch < 0x30; ch++ {
- secKeyRandomChars[i] = ch
- i++
- }
- for ch := byte(0x3a); ch < 0x7F; ch++ {
- secKeyRandomChars[i] = ch
- i++
- }
-}
-
-type byteReader interface {
- ReadByte() (byte, error)
-}
-
-// readHixieLength reads frame length for frame type 0x80-0xFF
-// as defined in Hixie draft.
-// See section 4.2 Data framing.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2
-func readHixieLength(r byteReader) (length int64, lengthFields []byte, err error) {
- for {
- c, err := r.ReadByte()
- if err != nil {
- return 0, nil, err
- }
- lengthFields = append(lengthFields, c)
- length = length*128 + int64(c&0x7f)
- if c&0x80 == 0 {
- break
- }
- }
- return
-}
-
-// A hixieLengthFrameReader is a reader for frame type 0x80-0xFF
-// as defined in hixie draft.
-type hixieLengthFrameReader struct {
- reader io.Reader
- FrameType byte
- Length int64
- header *bytes.Buffer
- length int
-}
-
-func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err error) {
- return frame.reader.Read(msg)
-}
-
-func (frame *hixieLengthFrameReader) PayloadType() byte {
- if frame.FrameType == '\xff' && frame.Length == 0 {
- return CloseFrame
- }
- return UnknownFrame
-}
-
-func (frame *hixieLengthFrameReader) HeaderReader() io.Reader {
- if frame.header == nil {
- return nil
- }
- if frame.header.Len() == 0 {
- frame.header = nil
- return nil
- }
- return frame.header
-}
-
-func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length }
-
-// A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F
-// as defined in hixie draft.
-type hixieSentinelFrameReader struct {
- reader *bufio.Reader
- FrameType byte
- header *bytes.Buffer
- data []byte
- seenTrailer bool
- trailer *bytes.Buffer
-}
-
-func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err error) {
- if len(frame.data) == 0 {
- if frame.seenTrailer {
- return 0, io.EOF
- }
- frame.data, err = frame.reader.ReadSlice('\xff')
- if err == nil {
- frame.seenTrailer = true
- frame.data = frame.data[:len(frame.data)-1] // trim \xff
- frame.trailer = bytes.NewBuffer([]byte{0xff})
- }
- }
- n = copy(msg, frame.data)
- frame.data = frame.data[n:]
- return n, err
-}
-
-func (frame *hixieSentinelFrameReader) PayloadType() byte {
- if frame.FrameType == 0 {
- return TextFrame
- }
- return UnknownFrame
-}
-
-func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader {
- if frame.header == nil {
- return nil
- }
- if frame.header.Len() == 0 {
- frame.header = nil
- return nil
- }
- return frame.header
-}
-
-func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader {
- if frame.trailer == nil {
- return nil
- }
- if frame.trailer.Len() == 0 {
- frame.trailer = nil
- return nil
- }
- return frame.trailer
-}
-
-func (frame *hixieSentinelFrameReader) Len() int { return -1 }
-
-// A HixieFrameReaderFactory creates new frame reader based on its frame type.
-type hixieFrameReaderFactory struct {
- *bufio.Reader
-}
-
-func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err error) {
- var header []byte
- var b byte
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- if b&0x80 == 0x80 {
- length, lengthFields, err := readHixieLength(buf.Reader)
- if err != nil {
- return nil, err
- }
- if length == 0 {
- return nil, io.EOF
- }
- header = append(header, lengthFields...)
- return &hixieLengthFrameReader{
- reader: io.LimitReader(buf.Reader, length),
- FrameType: b,
- Length: length,
- header: bytes.NewBuffer(header)}, err
- }
- return &hixieSentinelFrameReader{
- reader: buf.Reader,
- FrameType: b,
- header: bytes.NewBuffer(header)}, err
-}
-
-type hixiFrameWriter struct {
- writer *bufio.Writer
-}
-
-func (frame *hixiFrameWriter) Write(msg []byte) (n int, err error) {
- frame.writer.WriteByte(0)
- frame.writer.Write(msg)
- frame.writer.WriteByte(0xff)
- err = frame.writer.Flush()
- return len(msg), err
-}
-
-func (frame *hixiFrameWriter) Close() error { return nil }
-
-type hixiFrameWriterFactory struct {
- *bufio.Writer
-}
-
-func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
- if payloadType != TextFrame {
- return nil, ErrNotSupported
- }
- return &hixiFrameWriter{writer: buf.Writer}, nil
-}
-
-type hixiFrameHandler struct {
- conn *Conn
-}
-
-func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
- if header := frame.HeaderReader(); header != nil {
- io.Copy(ioutil.Discard, header)
- }
- if frame.PayloadType() != TextFrame {
- io.Copy(ioutil.Discard, frame)
- return nil, nil
- }
- return frame, nil
-}
-
-func (handler *hixiFrameHandler) WriteClose(_ int) (err error) {
- handler.conn.wio.Lock()
- defer handler.conn.wio.Unlock()
- closingFrame := []byte{'\xff', '\x00'}
- handler.conn.buf.Write(closingFrame)
- return handler.conn.buf.Flush()
-}
-
-// newHixiConn creates a new WebSocket connection speaking hixie draft protocol.
-func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- if buf == nil {
- br := bufio.NewReader(rwc)
- bw := bufio.NewWriter(rwc)
- buf = bufio.NewReadWriter(br, bw)
- }
- ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
- frameReaderFactory: hixieFrameReaderFactory{buf.Reader},
- frameWriterFactory: hixiFrameWriterFactory{buf.Writer},
- PayloadType: TextFrame}
- ws.frameHandler = &hixiFrameHandler{ws}
- return ws
-}
-
-// getChallengeResponse computes the expected response from the
-// challenge as described in section 5.1 Opening Handshake steps 42 to
-// 43 of http://www.whatwg.org/specs/web-socket-protocol/
-func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err error) {
- // 41. Let /challenge/ be the concatenation of /number_1/, expressed
- // a big-endian 32 bit integer, /number_2/, expressed in a big-
- // endian 32 bit integer, and the eight bytes of /key_3/ in the
- // order they were sent to the wire.
- challenge := make([]byte, 16)
- binary.BigEndian.PutUint32(challenge[0:], number1)
- binary.BigEndian.PutUint32(challenge[4:], number2)
- copy(challenge[8:], key3)
-
- // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
- // endian 128 bit string.
- h := md5.New()
- if _, err = h.Write(challenge); err != nil {
- return
- }
- expected = h.Sum(nil)
- return
-}
-
-// Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func generateKeyNumber() (key string, number uint32) {
- // 16. Let /spaces_n/ be a random integer from 1 to 12 inclusive.
- spaces := rand.Intn(12) + 1
-
- // 17. Let /max_n/ be the largest integer not greater than
- // 4,294,967,295 divided by /spaces_n/
- max := int(4294967295 / uint32(spaces))
-
- // 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
- number = uint32(rand.Intn(max + 1))
-
- // 19. Let /product_n/ be the result of multiplying /number_n/ and
- // /spaces_n/ together.
- product := number * uint32(spaces)
-
- // 20. Let /key_n/ be a string consisting of /product_n/, expressed
- // in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
- // to U+0039 DIGIT NINE (9).
- key = fmt.Sprintf("%d", product)
-
- // 21. Insert between one and twelve random characters from the ranges
- // U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
- // positions.
- n := rand.Intn(12) + 1
- for i := 0; i < n; i++ {
- pos := rand.Intn(len(key)) + 1
- ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
- key = key[0:pos] + string(ch) + key[pos:]
- }
-
- // 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
- // positions other than the start or end of the string.
- for i := 0; i < spaces; i++ {
- pos := rand.Intn(len(key)-1) + 1
- key = key[0:pos] + " " + key[pos:]
- }
-
- return
-}
-
-// Generates handshake key_3 as described in 4.1 Opening handshake step 26.
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func generateKey3() (key []byte) {
- // 26. Let /key3/ be a string consisting of eight random bytes (or
- // equivalently, a random 64 bit integer encoded in big-endian order).
- key = make([]byte, 8)
- for i := 0; i < 8; i++ {
- key[i] = byte(rand.Intn(256))
- }
- return
-}
-
-// Cilent handhake described in (soon obsolete)
-// draft-ietf-hybi-thewebsocket-protocol-00
-// (draft-hixie-thewebsocket-protocol-76)
-func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
- switch config.Version {
- case ProtocolVersionHixie76, ProtocolVersionHybi00:
- default:
- panic("wrong protocol version.")
- }
- // 4.1. Opening handshake.
- // Step 5. send a request line.
- bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
-
- // Step 6-14. push request headers in fields.
- fields := []string{
- "Upgrade: WebSocket\r\n",
- "Connection: Upgrade\r\n",
- "Host: " + config.Location.Host + "\r\n",
- "Origin: " + config.Origin.String() + "\r\n",
- }
- if len(config.Protocol) > 0 {
- if len(config.Protocol) != 1 {
- return ErrBadWebSocketProtocol
- }
- fields = append(fields, "Sec-WebSocket-Protocol: "+config.Protocol[0]+"\r\n")
- }
- // TODO(ukai): Step 15. send cookie if any.
-
- // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
- key1, number1 := generateKeyNumber()
- key2, number2 := generateKeyNumber()
- if config.handshakeData != nil {
- key1 = config.handshakeData["key1"]
- n, err := strconv.ParseUint(config.handshakeData["number1"], 10, 32)
- if err != nil {
- panic(err)
- }
- number1 = uint32(n)
- key2 = config.handshakeData["key2"]
- n, err = strconv.ParseUint(config.handshakeData["number2"], 10, 32)
- if err != nil {
- panic(err)
- }
- number2 = uint32(n)
- }
- fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n")
- fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n")
-
- // Step 24. shuffle fields and send them out.
- for i := 1; i < len(fields); i++ {
- j := rand.Intn(i)
- fields[i], fields[j] = fields[j], fields[i]
- }
- for i := 0; i < len(fields); i++ {
- bw.WriteString(fields[i])
- }
- // Step 25. send CRLF.
- bw.WriteString("\r\n")
-
- // Step 26. generate 8 bytes random key.
- key3 := generateKey3()
- if config.handshakeData != nil {
- key3 = []byte(config.handshakeData["key3"])
- }
- // Step 27. send it out.
- bw.Write(key3)
- if err = bw.Flush(); err != nil {
- return
- }
-
- // Step 28-29, 32-40. read response from server.
- resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
- if err != nil {
- return err
- }
- // Step 30. check response code is 101.
- if resp.StatusCode != 101 {
- return ErrBadStatus
- }
-
- // Step 41. check websocket headers.
- if resp.Header.Get("Upgrade") != "WebSocket" ||
- strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
- return ErrBadUpgrade
- }
-
- if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
- return ErrBadWebSocketOrigin
- }
-
- if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
- return ErrBadWebSocketLocation
- }
-
- if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
- return ErrBadWebSocketProtocol
- }
-
- // Step 42-43. get expected data from challenge data.
- expected, err := getChallengeResponse(number1, number2, key3)
- if err != nil {
- return err
- }
-
- // Step 44. read 16 bytes from server.
- reply := make([]byte, 16)
- if _, err = io.ReadFull(br, reply); err != nil {
- return err
- }
-
- // Step 45. check the reply equals to expected data.
- if !bytes.Equal(expected, reply) {
- return ErrChallengeResponse
- }
- // WebSocket connection is established.
- return
-}
-
-// Client Handshake described in (soon obsolete)
-// draft-hixie-thewebsocket-protocol-75.
-func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
- if config.Version != ProtocolVersionHixie75 {
- panic("wrong protocol version.")
- }
- bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
- bw.WriteString("Upgrade: WebSocket\r\n")
- bw.WriteString("Connection: Upgrade\r\n")
- bw.WriteString("Host: " + config.Location.Host + "\r\n")
- bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
- if len(config.Protocol) > 0 {
- if len(config.Protocol) != 1 {
- return ErrBadWebSocketProtocol
- }
- bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
- }
- bw.WriteString("\r\n")
- bw.Flush()
- resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
- if err != nil {
- return
- }
- if resp.Status != "101 Web Socket Protocol Handshake" {
- return ErrBadStatus
- }
- if resp.Header.Get("Upgrade") != "WebSocket" ||
- resp.Header.Get("Connection") != "Upgrade" {
- return ErrBadUpgrade
- }
- if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
- return ErrBadWebSocketOrigin
- }
- if resp.Header.Get("Websocket-Location") != config.Location.String() {
- return ErrBadWebSocketLocation
- }
- if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
- return ErrBadWebSocketProtocol
- }
- return
-}
-
-// newHixieClientConn returns new WebSocket connection speaking hixie draft protocol.
-func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
- return newHixieConn(config, buf, rwc, nil)
-}
-
-// Gets key number from Sec-WebSocket-Key<n>: field as described
-// in 5.2 Sending the server's opening handshake, 4.
-func getKeyNumber(s string) (r uint32) {
- // 4. Let /key-number_n/ be the digits (characters in the range
- // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
- // interpreted as a base ten integer, ignoring all other characters
- // in /key_n/.
- r = 0
- for i := 0; i < len(s); i++ {
- if s[i] >= '0' && s[i] <= '9' {
- r = r*10 + uint32(s[i]) - '0'
- }
- }
- return
-}
-
-// A Hixie76ServerHandshaker performs a server handshake using
-// hixie draft 76 protocol.
-type hixie76ServerHandshaker struct {
- *Config
- challengeResponse []byte
-}
-
-func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
- c.Version = ProtocolVersionHybi00
- if req.Method != "GET" {
- return http.StatusMethodNotAllowed, ErrBadRequestMethod
- }
- // HTTP version can be safely ignored.
-
- if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
- strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
- return http.StatusBadRequest, ErrNotWebSocket
- }
-
- // TODO(ukai): check Host
- c.Origin, err = url.ParseRequest(req.Header.Get("Origin"))
- if err != nil {
- return http.StatusBadRequest, err
- }
-
- key1 := req.Header.Get("Sec-Websocket-Key1")
- if key1 == "" {
- return http.StatusBadRequest, ErrChallengeResponse
- }
- key2 := req.Header.Get("Sec-Websocket-Key2")
- if key2 == "" {
- return http.StatusBadRequest, ErrChallengeResponse
- }
- key3 := make([]byte, 8)
- if _, err := io.ReadFull(buf, key3); err != nil {
- return http.StatusBadRequest, ErrChallengeResponse
- }
-
- var scheme string
- if req.TLS != nil {
- scheme = "wss"
- } else {
- scheme = "ws"
- }
- c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RequestURI())
- if err != nil {
- return http.StatusBadRequest, err
- }
-
- // Step 4. get key number in Sec-WebSocket-Key<n> fields.
- keyNumber1 := getKeyNumber(key1)
- keyNumber2 := getKeyNumber(key2)
-
- // Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
- space1 := uint32(strings.Count(key1, " "))
- space2 := uint32(strings.Count(key2, " "))
- if space1 == 0 || space2 == 0 {
- return http.StatusBadRequest, ErrChallengeResponse
- }
-
- // Step 6. key number must be an integral multiple of spaces.
- if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
- return http.StatusBadRequest, ErrChallengeResponse
- }
-
- // Step 7. let part be key number divided by spaces.
- part1 := keyNumber1 / space1
- part2 := keyNumber2 / space2
-
- // Step 8. let challenge be concatenation of part1, part2 and key3.
- // Step 9. get MD5 fingerprint of challenge.
- c.challengeResponse, err = getChallengeResponse(part1, part2, key3)
- if err != nil {
- return http.StatusInternalServerError, err
- }
- protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
- protocols := strings.Split(protocol, ",")
- for i := 0; i < len(protocols); i++ {
- c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
- }
-
- return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
- if len(c.Protocol) > 0 {
- if len(c.Protocol) != 1 {
- return ErrBadWebSocketProtocol
- }
- }
-
- // Step 10. send response status line.
- buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
- // Step 11. send response headers.
- buf.WriteString("Upgrade: WebSocket\r\n")
- buf.WriteString("Connection: Upgrade\r\n")
- buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n")
- buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n")
- if len(c.Protocol) > 0 {
- buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
- }
- // Step 12. send CRLF.
- buf.WriteString("\r\n")
- // Step 13. send response data.
- buf.Write(c.challengeResponse)
- return buf.Flush()
-}
-
-func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
- return newHixieServerConn(c.Config, buf, rwc, request)
-}
-
-// A hixie75ServerHandshaker performs a server handshake using
-// hixie draft 75 protocol.
-type hixie75ServerHandshaker struct {
- *Config
-}
-
-func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
- c.Version = ProtocolVersionHixie75
- if req.Method != "GET" || req.Proto != "HTTP/1.1" {
- return http.StatusMethodNotAllowed, ErrBadRequestMethod
- }
- if req.Header.Get("Upgrade") != "WebSocket" {
- return http.StatusBadRequest, ErrNotWebSocket
- }
- if req.Header.Get("Connection") != "Upgrade" {
- return http.StatusBadRequest, ErrNotWebSocket
- }
- c.Origin, err = url.ParseRequest(strings.TrimSpace(req.Header.Get("Origin")))
- if err != nil {
- return http.StatusBadRequest, err
- }
-
- var scheme string
- if req.TLS != nil {
- scheme = "wss"
- } else {
- scheme = "ws"
- }
- c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RequestURI())
- if err != nil {
- return http.StatusBadRequest, err
- }
- protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
- protocols := strings.Split(protocol, ",")
- for i := 0; i < len(protocols); i++ {
- c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
- }
-
- return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
- if len(c.Protocol) > 0 {
- if len(c.Protocol) != 1 {
- return ErrBadWebSocketProtocol
- }
- }
-
- buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
- buf.WriteString("Upgrade: WebSocket\r\n")
- buf.WriteString("Connection: Upgrade\r\n")
- buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n")
- buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n")
- if len(c.Protocol) > 0 {
- buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
- }
- buf.WriteString("\r\n")
- return buf.Flush()
-}
-
-func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
- return newHixieServerConn(c.Config, buf, rwc, request)
-}
-
-// newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol.
-func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- return newHixieConn(config, buf, rwc, request)
-}
diff --git a/libgo/go/websocket/hixie_test.go b/libgo/go/websocket/hixie_test.go
deleted file mode 100644
index bf537c01b73..00000000000
--- a/libgo/go/websocket/hixie_test.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strings"
- "testing"
-)
-
-// Test the getChallengeResponse function with values from section
-// 5.1 of the specification steps 18, 26, and 43 from
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func TestHixie76Challenge(t *testing.T) {
- var part1 uint32 = 777007543
- var part2 uint32 = 114997259
- key3 := []byte{0x47, 0x30, 0x22, 0x2D, 0x5A, 0x3F, 0x47, 0x58}
- expected := []byte("0st3Rl&q-2ZU^weu")
-
- response, err := getChallengeResponse(part1, part2, key3)
- if err != nil {
- t.Errorf("getChallengeResponse: returned error %v", err)
- return
- }
- if !bytes.Equal(expected, response) {
- t.Errorf("getChallengeResponse: expected %q got %q", expected, response)
- }
-}
-
-func TestHixie76ClientHandshake(t *testing.T) {
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
- br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 WebSocket Protocol Handshake
-Upgrade: WebSocket
-Connection: Upgrade
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Location: ws://example.com/demo
-Sec-WebSocket-Protocol: sample
-
-8jKS'y:G*Co,Wxa-`))
-
- var err error
- config := new(Config)
- config.Location, err = url.ParseRequest("ws://example.com/demo")
- if err != nil {
- t.Fatal("location url", err)
- }
- config.Origin, err = url.ParseRequest("http://example.com")
- if err != nil {
- t.Fatal("origin url", err)
- }
- config.Protocol = append(config.Protocol, "sample")
- config.Version = ProtocolVersionHixie76
-
- config.handshakeData = map[string]string{
- "key1": "4 @1 46546xW%0l 1 5",
- "number1": "829309203",
- "key2": "12998 5 Y3 1 .P00",
- "number2": "259970620",
- "key3": "^n:ds[4U",
- }
- err = hixie76ClientHandshake(config, br, bw)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- req, err := http.ReadRequest(bufio.NewReader(b))
- if err != nil {
- t.Fatalf("read request: %v", err)
- }
- if req.Method != "GET" {
- t.Errorf("request method expected GET, but got %q", req.Method)
- }
- if req.URL.Path != "/demo" {
- t.Errorf("request path expected /demo, but got %q", req.URL.Path)
- }
- if req.Proto != "HTTP/1.1" {
- t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
- }
- if req.Host != "example.com" {
- t.Errorf("request Host expected example.com, but got %v", req.Host)
- }
- var expectedHeader = map[string]string{
- "Connection": "Upgrade",
- "Upgrade": "WebSocket",
- "Origin": "http://example.com",
- "Sec-Websocket-Key1": config.handshakeData["key1"],
- "Sec-Websocket-Key2": config.handshakeData["key2"],
- "Sec-WebSocket-Protocol": config.Protocol[0],
- }
- for k, v := range expectedHeader {
- if req.Header.Get(k) != v {
- t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
- }
- }
-}
-
-func TestHixie76ServerHandshake(t *testing.T) {
- config := new(Config)
- handshaker := &hixie76ServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /demo HTTP/1.1
-Host: example.com
-Connection: Upgrade
-Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
-Sec-WebSocket-Protocol: sample
-Upgrade: WebSocket
-Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
-Origin: http://example.com
-
-^n:ds[4U`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 WebSocket Protocol Handshake",
- "Upgrade: WebSocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Origin: http://example.com",
- "Sec-WebSocket-Location: ws://example.com/demo",
- "Sec-WebSocket-Protocol: sample",
- "", ""}, "\r\n") + "8jKS'y:G*Co,Wxa-"
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
-
-func TestHixie76SkipLengthFrame(t *testing.T) {
- b := []byte{'\x80', '\x01', 'x', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
- buf := bytes.NewBuffer(b)
- br := bufio.NewReader(buf)
- bw := bufio.NewWriter(buf)
- config := newConfig(t, "/")
- ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
- msg := make([]byte, 5)
- n, err := ws.Read(msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- if !bytes.Equal(b[4:9], msg[0:n]) {
- t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
- }
-}
-
-func TestHixie76SkipNoUTF8Frame(t *testing.T) {
- b := []byte{'\x01', 'n', '\xff', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
- buf := bytes.NewBuffer(b)
- br := bufio.NewReader(buf)
- bw := bufio.NewWriter(buf)
- config := newConfig(t, "/")
- ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
- msg := make([]byte, 5)
- n, err := ws.Read(msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- if !bytes.Equal(b[4:9], msg[0:n]) {
- t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
- }
-}
-
-func TestHixie76ClosingFrame(t *testing.T) {
- b := []byte{0, 'h', 'e', 'l', 'l', 'o', '\xff'}
- buf := bytes.NewBuffer(b)
- br := bufio.NewReader(buf)
- bw := bufio.NewWriter(buf)
- config := newConfig(t, "/")
- ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
- msg := make([]byte, 5)
- n, err := ws.Read(msg)
- if err != nil {
- t.Errorf("read: %v", err)
- }
- if !bytes.Equal(b[1:6], msg[0:n]) {
- t.Errorf("Read: expected %q got %q", b[1:6], msg[0:n])
- }
- n, err = ws.Read(msg)
- if err != io.EOF {
- t.Errorf("read: %v", err)
- }
-}
diff --git a/libgo/go/websocket/hybi.go b/libgo/go/websocket/hybi.go
deleted file mode 100644
index 6b0c5286f28..00000000000
--- a/libgo/go/websocket/hybi.go
+++ /dev/null
@@ -1,549 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-// This file implements a protocol of hybi draft.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-
-import (
- "bufio"
- "bytes"
- "crypto/rand"
- "crypto/sha1"
- "encoding/base64"
- "encoding/binary"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "strings"
-)
-
-const (
- websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
- closeStatusNormal = 1000
- closeStatusGoingAway = 1001
- closeStatusProtocolError = 1002
- closeStatusUnsupportedData = 1003
- closeStatusFrameTooLarge = 1004
- closeStatusNoStatusRcvd = 1005
- closeStatusAbnormalClosure = 1006
- closeStatusBadMessageData = 1007
- closeStatusPolicyViolation = 1008
- closeStatusTooBigData = 1009
- closeStatusExtensionMismatch = 1010
-
- maxControlFramePayloadLength = 125
-)
-
-var (
- ErrBadMaskingKey = &ProtocolError{"bad masking key"}
- ErrBadPongMessage = &ProtocolError{"bad pong message"}
- ErrBadClosingStatus = &ProtocolError{"bad closing status"}
- ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
- ErrNotImplemented = &ProtocolError{"not implemented"}
-)
-
-// A hybiFrameHeader is a frame header as defined in hybi draft.
-type hybiFrameHeader struct {
- Fin bool
- Rsv [3]bool
- OpCode byte
- Length int64
- MaskingKey []byte
-
- data *bytes.Buffer
-}
-
-// A hybiFrameReader is a reader for hybi frame.
-type hybiFrameReader struct {
- reader io.Reader
-
- header hybiFrameHeader
- pos int64
- length int
-}
-
-func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
- n, err = frame.reader.Read(msg)
- if err != nil {
- return 0, err
- }
- if frame.header.MaskingKey != nil {
- for i := 0; i < n; i++ {
- msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
- frame.pos++
- }
- }
- return n, err
-}
-
-func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
-
-func (frame *hybiFrameReader) HeaderReader() io.Reader {
- if frame.header.data == nil {
- return nil
- }
- if frame.header.data.Len() == 0 {
- return nil
- }
- return frame.header.data
-}
-
-func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hybiFrameReader) Len() (n int) { return frame.length }
-
-// A hybiFrameReaderFactory creates new frame reader based on its frame type.
-type hybiFrameReaderFactory struct {
- *bufio.Reader
-}
-
-// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
-// See Section 5.2 Base Frameing protocol for detail.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
-func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
- hybiFrame := new(hybiFrameReader)
- frame = hybiFrame
- var header []byte
- var b byte
- // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
- for i := 0; i < 3; i++ {
- j := uint(6 - i)
- hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
- }
- hybiFrame.header.OpCode = header[0] & 0x0f
-
- // Second byte. Mask/Payload len(7bits)
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- mask := (b & 0x80) != 0
- b &= 0x7f
- lengthFields := 0
- switch {
- case b <= 125: // Payload length 7bits.
- hybiFrame.header.Length = int64(b)
- case b == 126: // Payload length 7+16bits
- lengthFields = 2
- case b == 127: // Payload length 7+64bits
- lengthFields = 8
- }
- for i := 0; i < lengthFields; i++ {
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
- }
- if mask {
- // Masking key. 4 bytes.
- for i := 0; i < 4; i++ {
- b, err = buf.ReadByte()
- if err != nil {
- return
- }
- header = append(header, b)
- hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
- }
- }
- hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
- hybiFrame.header.data = bytes.NewBuffer(header)
- hybiFrame.length = len(header) + int(hybiFrame.header.Length)
- return
-}
-
-// A HybiFrameWriter is a writer for hybi frame.
-type hybiFrameWriter struct {
- writer *bufio.Writer
-
- header *hybiFrameHeader
-}
-
-func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
- var header []byte
- var b byte
- if frame.header.Fin {
- b |= 0x80
- }
- for i := 0; i < 3; i++ {
- if frame.header.Rsv[i] {
- j := uint(6 - i)
- b |= 1 << j
- }
- }
- b |= frame.header.OpCode
- header = append(header, b)
- if frame.header.MaskingKey != nil {
- b = 0x80
- } else {
- b = 0
- }
- lengthFields := 0
- length := len(msg)
- switch {
- case length <= 125:
- b |= byte(length)
- case length < 65536:
- b |= 126
- lengthFields = 2
- default:
- b |= 127
- lengthFields = 8
- }
- header = append(header, b)
- for i := 0; i < lengthFields; i++ {
- j := uint((lengthFields - i - 1) * 8)
- b = byte((length >> j) & 0xff)
- header = append(header, b)
- }
- if frame.header.MaskingKey != nil {
- if len(frame.header.MaskingKey) != 4 {
- return 0, ErrBadMaskingKey
- }
- header = append(header, frame.header.MaskingKey...)
- frame.writer.Write(header)
- var data []byte
-
- for i := 0; i < length; i++ {
- data = append(data, msg[i]^frame.header.MaskingKey[i%4])
- }
- frame.writer.Write(data)
- err = frame.writer.Flush()
- return length, err
- }
- frame.writer.Write(header)
- frame.writer.Write(msg)
- err = frame.writer.Flush()
- return length, err
-}
-
-func (frame *hybiFrameWriter) Close() error { return nil }
-
-type hybiFrameWriterFactory struct {
- *bufio.Writer
- needMaskingKey bool
-}
-
-func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
- if buf.needMaskingKey {
- frameHeader.MaskingKey, err = generateMaskingKey()
- if err != nil {
- return nil, err
- }
- }
- return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
-}
-
-type hybiFrameHandler struct {
- conn *Conn
- payloadType byte
-}
-
-func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
- if handler.conn.IsServerConn() {
- // The client MUST mask all frames sent to the server.
- if frame.(*hybiFrameReader).header.MaskingKey == nil {
- handler.WriteClose(closeStatusProtocolError)
- return nil, io.EOF
- }
- } else {
- // The server MUST NOT mask all frames.
- if frame.(*hybiFrameReader).header.MaskingKey != nil {
- handler.WriteClose(closeStatusProtocolError)
- return nil, io.EOF
- }
- }
- if header := frame.HeaderReader(); header != nil {
- io.Copy(ioutil.Discard, header)
- }
- switch frame.PayloadType() {
- case ContinuationFrame:
- frame.(*hybiFrameReader).header.OpCode = handler.payloadType
- case TextFrame, BinaryFrame:
- handler.payloadType = frame.PayloadType()
- case CloseFrame:
- return nil, io.EOF
- case PingFrame:
- pingMsg := make([]byte, maxControlFramePayloadLength)
- n, err := io.ReadFull(frame, pingMsg)
- if err != nil && err != io.ErrUnexpectedEOF {
- return nil, err
- }
- io.Copy(ioutil.Discard, frame)
- n, err = handler.WritePong(pingMsg[:n])
- if err != nil {
- return nil, err
- }
- return nil, nil
- case PongFrame:
- return nil, ErrNotImplemented
- }
- return frame, nil
-}
-
-func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
- handler.conn.wio.Lock()
- defer handler.conn.wio.Unlock()
- w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
- if err != nil {
- return err
- }
- msg := make([]byte, 2)
- binary.BigEndian.PutUint16(msg, uint16(status))
- _, err = w.Write(msg)
- w.Close()
- return err
-}
-
-func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
- handler.conn.wio.Lock()
- defer handler.conn.wio.Unlock()
- w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
- if err != nil {
- return 0, err
- }
- n, err = w.Write(msg)
- w.Close()
- return n, err
-}
-
-// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
-func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- if buf == nil {
- br := bufio.NewReader(rwc)
- bw := bufio.NewWriter(rwc)
- buf = bufio.NewReadWriter(br, bw)
- }
- ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
- frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
- frameWriterFactory: hybiFrameWriterFactory{
- buf.Writer, request == nil},
- PayloadType: TextFrame,
- defaultCloseStatus: closeStatusNormal}
- ws.frameHandler = &hybiFrameHandler{conn: ws}
- return ws
-}
-
-// generateMaskingKey generates a masking key for a frame.
-func generateMaskingKey() (maskingKey []byte, err error) {
- maskingKey = make([]byte, 4)
- if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
- return
- }
- return
-}
-
-// genetateNonce geneates a nonce consisting of a randomly selected 16-byte
-// value that has been base64-encoded.
-func generateNonce() (nonce []byte) {
- key := make([]byte, 16)
- if _, err := io.ReadFull(rand.Reader, key); err != nil {
- panic(err)
- }
- nonce = make([]byte, 24)
- base64.StdEncoding.Encode(nonce, key)
- return
-}
-
-// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
-// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
-func getNonceAccept(nonce []byte) (expected []byte, err error) {
- h := sha1.New()
- if _, err = h.Write(nonce); err != nil {
- return
- }
- if _, err = h.Write([]byte(websocketGUID)); err != nil {
- return
- }
- expected = make([]byte, 28)
- base64.StdEncoding.Encode(expected, h.Sum(nil))
- return
-}
-
-func isHybiVersion(version int) bool {
- switch version {
- case ProtocolVersionHybi08, ProtocolVersionHybi13:
- return true
- default:
- }
- return false
-}
-
-// Client handhake described in draft-ietf-hybi-thewebsocket-protocol-17
-func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
- if !isHybiVersion(config.Version) {
- panic("wrong protocol version.")
- }
-
- bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
-
- bw.WriteString("Host: " + config.Location.Host + "\r\n")
- bw.WriteString("Upgrade: websocket\r\n")
- bw.WriteString("Connection: Upgrade\r\n")
- nonce := generateNonce()
- if config.handshakeData != nil {
- nonce = []byte(config.handshakeData["key"])
- }
- bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
- if config.Version == ProtocolVersionHybi13 {
- bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
- } else if config.Version == ProtocolVersionHybi08 {
- bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
- }
- bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
- if len(config.Protocol) > 0 {
- bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
- }
- // TODO(ukai): send extensions.
- // TODO(ukai): send cookie if any.
-
- bw.WriteString("\r\n")
- if err = bw.Flush(); err != nil {
- return err
- }
-
- resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
- if err != nil {
- return err
- }
- if resp.StatusCode != 101 {
- return ErrBadStatus
- }
- if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
- strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
- return ErrBadUpgrade
- }
- expectedAccept, err := getNonceAccept(nonce)
- if err != nil {
- return err
- }
- if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
- return ErrChallengeResponse
- }
- if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
- return ErrUnsupportedExtensions
- }
- offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
- if offeredProtocol != "" {
- protocolMatched := false
- for i := 0; i < len(config.Protocol); i++ {
- if config.Protocol[i] == offeredProtocol {
- protocolMatched = true
- break
- }
- }
- if !protocolMatched {
- return ErrBadWebSocketProtocol
- }
- config.Protocol = []string{offeredProtocol}
- }
-
- return nil
-}
-
-// newHybiClientConn creates a client WebSocket connection after handshake.
-func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
- return newHybiConn(config, buf, rwc, nil)
-}
-
-// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
-type hybiServerHandshaker struct {
- *Config
- accept []byte
-}
-
-func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
- c.Version = ProtocolVersionHybi13
- if req.Method != "GET" {
- return http.StatusMethodNotAllowed, ErrBadRequestMethod
- }
- // HTTP version can be safely ignored.
-
- if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
- !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
- return http.StatusBadRequest, ErrNotWebSocket
- }
-
- key := req.Header.Get("Sec-Websocket-Key")
- if key == "" {
- return http.StatusBadRequest, ErrChallengeResponse
- }
- version := req.Header.Get("Sec-Websocket-Version")
- var origin string
- switch version {
- case "13":
- c.Version = ProtocolVersionHybi13
- origin = req.Header.Get("Origin")
- case "8":
- c.Version = ProtocolVersionHybi08
- origin = req.Header.Get("Sec-Websocket-Origin")
- default:
- return http.StatusBadRequest, ErrBadWebSocketVersion
- }
- c.Origin, err = url.ParseRequest(origin)
- if err != nil {
- return http.StatusForbidden, err
- }
- var scheme string
- if req.TLS != nil {
- scheme = "wss"
- } else {
- scheme = "ws"
- }
- c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RequestURI())
- if err != nil {
- return http.StatusBadRequest, err
- }
- protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
- protocols := strings.Split(protocol, ",")
- for i := 0; i < len(protocols); i++ {
- c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
- }
- c.accept, err = getNonceAccept([]byte(key))
- if err != nil {
- return http.StatusInternalServerError, err
- }
- return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
- if len(c.Protocol) > 0 {
- if len(c.Protocol) != 1 {
- return ErrBadWebSocketProtocol
- }
- }
- buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
- buf.WriteString("Upgrade: websocket\r\n")
- buf.WriteString("Connection: Upgrade\r\n")
- buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
- if len(c.Protocol) > 0 {
- buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
- }
- // TODO(ukai): support extensions
- buf.WriteString("\r\n")
- return buf.Flush()
-}
-
-func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- return newHybiServerConn(c.Config, buf, rwc, request)
-}
-
-// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
-func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
- return newHybiConn(config, buf, rwc, request)
-}
diff --git a/libgo/go/websocket/hybi_test.go b/libgo/go/websocket/hybi_test.go
deleted file mode 100644
index 60375ff32ad..00000000000
--- a/libgo/go/websocket/hybi_test.go
+++ /dev/null
@@ -1,584 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strings"
- "testing"
-)
-
-// Test the getNonceAccept function with values in
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-func TestSecWebSocketAccept(t *testing.T) {
- nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
- expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
- accept, err := getNonceAccept(nonce)
- if err != nil {
- t.Errorf("getNonceAccept: returned error %v", err)
- return
- }
- if !bytes.Equal(expected, accept) {
- t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
- }
-}
-
-func TestHybiClientHandshake(t *testing.T) {
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
- br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
- var err error
- config := new(Config)
- config.Location, err = url.ParseRequest("ws://server.example.com/chat")
- if err != nil {
- t.Fatal("location url", err)
- }
- config.Origin, err = url.ParseRequest("http://example.com")
- if err != nil {
- t.Fatal("origin url", err)
- }
- config.Protocol = append(config.Protocol, "chat")
- config.Protocol = append(config.Protocol, "superchat")
- config.Version = ProtocolVersionHybi13
-
- config.handshakeData = map[string]string{
- "key": "dGhlIHNhbXBsZSBub25jZQ==",
- }
- err = hybiClientHandshake(config, br, bw)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- req, err := http.ReadRequest(bufio.NewReader(b))
- if err != nil {
- t.Fatalf("read request: %v", err)
- }
- if req.Method != "GET" {
- t.Errorf("request method expected GET, but got %q", req.Method)
- }
- if req.URL.Path != "/chat" {
- t.Errorf("request path expected /chat, but got %q", req.URL.Path)
- }
- if req.Proto != "HTTP/1.1" {
- t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
- }
- if req.Host != "server.example.com" {
- t.Errorf("request Host expected server.example.com, but got %v", req.Host)
- }
- var expectedHeader = map[string]string{
- "Connection": "Upgrade",
- "Upgrade": "websocket",
- "Sec-Websocket-Key": config.handshakeData["key"],
- "Origin": config.Origin.String(),
- "Sec-Websocket-Protocol": "chat, superchat",
- "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
- }
- for k, v := range expectedHeader {
- if req.Header.Get(k) != v {
- t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
- }
- }
-}
-
-func TestHybiClientHandshakeHybi08(t *testing.T) {
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
- br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
- var err error
- config := new(Config)
- config.Location, err = url.ParseRequest("ws://server.example.com/chat")
- if err != nil {
- t.Fatal("location url", err)
- }
- config.Origin, err = url.ParseRequest("http://example.com")
- if err != nil {
- t.Fatal("origin url", err)
- }
- config.Protocol = append(config.Protocol, "chat")
- config.Protocol = append(config.Protocol, "superchat")
- config.Version = ProtocolVersionHybi08
-
- config.handshakeData = map[string]string{
- "key": "dGhlIHNhbXBsZSBub25jZQ==",
- }
- err = hybiClientHandshake(config, br, bw)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- req, err := http.ReadRequest(bufio.NewReader(b))
- if err != nil {
- t.Fatalf("read request: %v", err)
- }
- if req.Method != "GET" {
- t.Errorf("request method expected GET, but got %q", req.Method)
- }
- if req.URL.Path != "/chat" {
- t.Errorf("request path expected /demo, but got %q", req.URL.Path)
- }
- if req.Proto != "HTTP/1.1" {
- t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
- }
- if req.Host != "server.example.com" {
- t.Errorf("request Host expected example.com, but got %v", req.Host)
- }
- var expectedHeader = map[string]string{
- "Connection": "Upgrade",
- "Upgrade": "websocket",
- "Sec-Websocket-Key": config.handshakeData["key"],
- "Sec-Websocket-Origin": config.Origin.String(),
- "Sec-Websocket-Protocol": "chat, superchat",
- "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi08),
- }
- for k, v := range expectedHeader {
- if req.Header.Get(k) != v {
- t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
- }
- }
-}
-
-func TestHybiServerHandshake(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 13
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- config.Protocol = []string{"chat"}
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
- "Sec-WebSocket-Protocol: chat",
- "", ""}, "\r\n")
-
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
-
-func TestHybiServerHandshakeHybi08(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 8
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- config.Protocol = []string{"chat"}
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
- "Sec-WebSocket-Protocol: chat",
- "", ""}, "\r\n")
-
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
-
-func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 9
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != ErrBadWebSocketVersion {
- t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
- }
- if code != http.StatusBadRequest {
- t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
- }
-}
-
-func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
- b := bytes.NewBuffer([]byte{})
- frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
- w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
- w.(*hybiFrameWriter).header = frameHeader
- _, err := w.Write(testPayload)
- w.Close()
- if err != nil {
- t.Errorf("Write error %q", err)
- }
- var expectedFrame []byte
- expectedFrame = append(expectedFrame, testHeader...)
- expectedFrame = append(expectedFrame, testMaskedPayload...)
- if !bytes.Equal(expectedFrame, b.Bytes()) {
- t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
- }
- frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
- r, err := frameReaderFactory.NewFrameReader()
- if err != nil {
- t.Errorf("Read error %q", err)
- }
- if header := r.HeaderReader(); header == nil {
- t.Errorf("no header")
- } else {
- actualHeader := make([]byte, r.Len())
- n, err := header.Read(actualHeader)
- if err != nil {
- t.Errorf("Read header error %q", err)
- } else {
- if n < len(testHeader) {
- t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
- }
- if !bytes.Equal(testHeader, actualHeader[:n]) {
- t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
- }
- }
- }
- if trailer := r.TrailerReader(); trailer != nil {
- t.Errorf("unexpected trailer %q", trailer)
- }
- frame := r.(*hybiFrameReader)
- if frameHeader.Fin != frame.header.Fin ||
- frameHeader.OpCode != frame.header.OpCode ||
- len(testPayload) != int(frame.header.Length) {
- t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
- }
- payload := make([]byte, len(testPayload))
- _, err = r.Read(payload)
- if err != nil {
- t.Errorf("read %v", err)
- }
- if !bytes.Equal(testPayload, payload) {
- t.Errorf("payload %q vs %q", testPayload, payload)
- }
-}
-
-func TestHybiShortTextFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
- payload := []byte("hello")
- testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
-
- payload = make([]byte, 125)
- testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiShortMaskedTextFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
- MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
- payload := []byte("hello")
- maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
- header := []byte{0x81, 0x85}
- header = append(header, frameHeader.MaskingKey...)
- testHybiFrame(t, header, payload, maskedPayload, frameHeader)
-}
-
-func TestHybiShortBinaryFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
- payload := []byte("hello")
- testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
-
- payload = make([]byte, 125)
- testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiControlFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
- payload := []byte("hello")
- testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
-
- frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
- testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
-
- frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
- payload = []byte{0x03, 0xe8} // 1000
- testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
-}
-
-func TestHybiLongFrame(t *testing.T) {
- frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
- payload := make([]byte, 126)
- testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
-
- payload = make([]byte, 65535)
- testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
-
- payload = make([]byte, 65536)
- testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
-}
-
-func TestHybiClientRead(t *testing.T) {
- wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
- 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
- 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
- msg := make([]byte, 512)
- n, err := conn.Read(msg)
- if err != nil {
- t.Errorf("read 1st frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 1st frame, expect 5, got %d", n)
- }
- if !bytes.Equal(wireData[2:7], msg[:n]) {
- t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
- }
- n, err = conn.Read(msg)
- if err != nil {
- t.Errorf("read 2nd frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 2nd frame, expect 5, got %d", n)
- }
- if !bytes.Equal(wireData[16:21], msg[:n]) {
- t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
- }
- n, err = conn.Read(msg)
- if err == nil {
- t.Errorf("read not EOF")
- }
- if n != 0 {
- t.Errorf("expect read 0, got %d", n)
- }
-}
-
-func TestHybiShortRead(t *testing.T) {
- wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
- 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
- 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
- step := 0
- pos := 0
- expectedPos := []int{2, 5, 16, 19}
- expectedLen := []int{3, 2, 3, 2}
- for {
- msg := make([]byte, 3)
- n, err := conn.Read(msg)
- if step >= len(expectedPos) {
- if err == nil {
- t.Errorf("read not EOF")
- }
- if n != 0 {
- t.Errorf("expect read 0, got %d", n)
- }
- return
- }
- pos = expectedPos[step]
- endPos := pos + expectedLen[step]
- if err != nil {
- t.Errorf("read from %d, got error %q", pos, err)
- return
- }
- if n != endPos-pos {
- t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
- }
- if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
- t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
- }
- step++
- }
-}
-
-func TestHybiServerRead(t *testing.T) {
- wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
- 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
- 0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
- 0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
- 0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
- 0x9a, 0xec, 0xc6, 0x48, 0x89, // world
- }
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
-
- expected := [][]byte{[]byte("hello"), []byte("world")}
-
- msg := make([]byte, 512)
- n, err := conn.Read(msg)
- if err != nil {
- t.Errorf("read 1st frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 1st frame, expect 5, got %d", n)
- }
- if !bytes.Equal(expected[0], msg[:n]) {
- t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
- }
-
- n, err = conn.Read(msg)
- if err != nil {
- t.Errorf("read 2nd frame, error %q", err)
- }
- if n != 5 {
- t.Errorf("read 2nd frame, expect 5, got %d", n)
- }
- if !bytes.Equal(expected[1], msg[:n]) {
- t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
- }
-
- n, err = conn.Read(msg)
- if err == nil {
- t.Errorf("read not EOF")
- }
- if n != 0 {
- t.Errorf("expect read 0, got %d", n)
- }
-}
-
-func TestHybiServerReadWithoutMasking(t *testing.T) {
- wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
- // server MUST close the connection upon receiving a non-masked frame.
- msg := make([]byte, 512)
- _, err := conn.Read(msg)
- if err != io.EOF {
- t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
- }
-}
-
-func TestHybiClientReadWithMasking(t *testing.T) {
- wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
- 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
- }
- br := bufio.NewReader(bytes.NewBuffer(wireData))
- bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
- conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
- // client MUST close the connection upon receiving a masked frame.
- msg := make([]byte, 512)
- _, err := conn.Read(msg)
- if err != io.EOF {
- t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
- }
-}
-
-// Test the hybiServerHandshaker supports firefox implementation and
-// checks Connection request header include (but it's not necessary
-// equal to) "upgrade"
-func TestHybiServerFirefoxHandshake(t *testing.T) {
- config := new(Config)
- handshaker := &hybiServerHandshaker{Config: config}
- br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: keep-alive, upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 13
-
-`))
- req, err := http.ReadRequest(br)
- if err != nil {
- t.Fatal("request", err)
- }
- code, err := handshaker.ReadHandshake(br, req)
- if err != nil {
- t.Errorf("handshake failed: %v", err)
- }
- if code != http.StatusSwitchingProtocols {
- t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
- }
- b := bytes.NewBuffer([]byte{})
- bw := bufio.NewWriter(b)
-
- config.Protocol = []string{"chat"}
-
- err = handshaker.AcceptHandshake(bw)
- if err != nil {
- t.Errorf("handshake response failed: %v", err)
- }
- expectedResponse := strings.Join([]string{
- "HTTP/1.1 101 Switching Protocols",
- "Upgrade: websocket",
- "Connection: Upgrade",
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
- "Sec-WebSocket-Protocol: chat",
- "", ""}, "\r\n")
-
- if b.String() != expectedResponse {
- t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
- }
-}
diff --git a/libgo/go/websocket/server.go b/libgo/go/websocket/server.go
deleted file mode 100644
index 63f48e25693..00000000000
--- a/libgo/go/websocket/server.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bufio"
- "fmt"
- "io"
- "net/http"
-)
-
-func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request) (conn *Conn, err error) {
- config := new(Config)
- var hs serverHandshaker = &hybiServerHandshaker{Config: config}
- code, err := hs.ReadHandshake(buf.Reader, req)
- if err == ErrBadWebSocketVersion {
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
- buf.WriteString("\r\n")
- buf.WriteString(err.Error())
- buf.Flush()
- return
- }
- if err != nil {
- hs = &hixie76ServerHandshaker{Config: config}
- code, err = hs.ReadHandshake(buf.Reader, req)
- }
- if err != nil {
- hs = &hixie75ServerHandshaker{Config: config}
- code, err = hs.ReadHandshake(buf.Reader, req)
- }
- if err != nil {
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- buf.WriteString("\r\n")
- buf.WriteString(err.Error())
- buf.Flush()
- return
- }
- config.Protocol = nil
-
- err = hs.AcceptHandshake(buf.Writer)
- if err != nil {
- code = http.StatusBadRequest
- fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
- buf.WriteString("\r\n")
- buf.Flush()
- return
- }
- conn = hs.NewServerConn(buf, rwc, req)
- return
-}
-
-/*
-Handler is an interface to a WebSocket.
-
-A trivial example server:
-
- package main
-
- import (
- "io"
- "net/http"
- "websocket"
- )
-
- // Echo the data received on the WebSocket.
- func EchoServer(ws *websocket.Conn) {
- io.Copy(ws, ws);
- }
-
- func main() {
- http.Handle("/echo", websocket.Handler(EchoServer));
- err := http.ListenAndServe(":12345", nil);
- if err != nil {
- panic("ListenAndServe: " + err.Error())
- }
- }
-*/
-type Handler func(*Conn)
-
-// ServeHTTP implements the http.Handler interface for a Web Socket
-func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- rwc, buf, err := w.(http.Hijacker).Hijack()
- if err != nil {
- panic("Hijack failed: " + err.Error())
- return
- }
- // The server should abort the WebSocket connection if it finds
- // the client did not send a handshake that matches with protocol
- // specification.
- defer rwc.Close()
- conn, err := newServerConn(rwc, buf, req)
- if err != nil {
- return
- }
- if conn == nil {
- panic("unepxected nil conn")
- }
- h(conn)
-}
diff --git a/libgo/go/websocket/websocket.go b/libgo/go/websocket/websocket.go
deleted file mode 100644
index f7aabc94b35..00000000000
--- a/libgo/go/websocket/websocket.go
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package websocket implements a client and server for the WebSocket protocol.
-// The protocol is defined at http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol
-package websocket
-
-import (
- "bufio"
- "crypto/tls"
- "encoding/json"
- "errors"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "sync"
- "time"
-)
-
-const (
- ProtocolVersionHixie75 = -75
- ProtocolVersionHixie76 = -76
- ProtocolVersionHybi00 = 0
- ProtocolVersionHybi08 = 8
- ProtocolVersionHybi13 = 13
- ProtocolVersionHybi = ProtocolVersionHybi13
- SupportedProtocolVersion = "13, 8"
-
- ContinuationFrame = 0
- TextFrame = 1
- BinaryFrame = 2
- CloseFrame = 8
- PingFrame = 9
- PongFrame = 10
- UnknownFrame = 255
-)
-
-// WebSocket protocol errors.
-type ProtocolError struct {
- ErrorString string
-}
-
-func (err *ProtocolError) Error() string { return err.ErrorString }
-
-var (
- ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
- ErrBadScheme = &ProtocolError{"bad scheme"}
- ErrBadStatus = &ProtocolError{"bad status"}
- ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
- ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
- ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
- ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
- ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
- ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
- ErrBadFrame = &ProtocolError{"bad frame"}
- ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
- ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
- ErrBadRequestMethod = &ProtocolError{"bad method"}
- ErrNotSupported = &ProtocolError{"not supported"}
-)
-
-// Addr is an implementation of net.Addr for WebSocket.
-type Addr struct {
- *url.URL
-}
-
-// Network returns the network type for a WebSocket, "websocket".
-func (addr *Addr) Network() string { return "websocket" }
-
-// Config is a WebSocket configuration
-type Config struct {
- // A WebSocket server address.
- Location *url.URL
-
- // A Websocket client origin.
- Origin *url.URL
-
- // WebSocket subprotocols.
- Protocol []string
-
- // WebSocket protocol version.
- Version int
-
- // TLS config for secure WebSocket (wss).
- TlsConfig *tls.Config
-
- handshakeData map[string]string
-}
-
-// serverHandshaker is an interface to handle WebSocket server side handshake.
-type serverHandshaker interface {
- // ReadHandshake reads handshake request message from client.
- // Returns http response code and error if any.
- ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
-
- // AcceptHandshake accepts the client handshake request and sends
- // handshake response back to client.
- AcceptHandshake(buf *bufio.Writer) (err error)
-
- // NewServerConn creates a new WebSocket connection.
- NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
-}
-
-// frameReader is an interface to read a WebSocket frame.
-type frameReader interface {
- // Reader is to read payload of the frame.
- io.Reader
-
- // PayloadType returns payload type.
- PayloadType() byte
-
- // HeaderReader returns a reader to read header of the frame.
- HeaderReader() io.Reader
-
- // TrailerReader returns a reader to read trailer of the frame.
- // If it returns nil, there is no trailer in the frame.
- TrailerReader() io.Reader
-
- // Len returns total length of the frame, including header and trailer.
- Len() int
-}
-
-// frameReaderFactory is an interface to creates new frame reader.
-type frameReaderFactory interface {
- NewFrameReader() (r frameReader, err error)
-}
-
-// frameWriter is an interface to write a WebSocket frame.
-type frameWriter interface {
- // Writer is to write playload of the frame.
- io.WriteCloser
-}
-
-// frameWriterFactory is an interface to create new frame writer.
-type frameWriterFactory interface {
- NewFrameWriter(payloadType byte) (w frameWriter, err error)
-}
-
-type frameHandler interface {
- HandleFrame(frame frameReader) (r frameReader, err error)
- WriteClose(status int) (err error)
-}
-
-// Conn represents a WebSocket connection.
-type Conn struct {
- config *Config
- request *http.Request
-
- buf *bufio.ReadWriter
- rwc io.ReadWriteCloser
-
- rio sync.Mutex
- frameReaderFactory
- frameReader
-
- wio sync.Mutex
- frameWriterFactory
-
- frameHandler
- PayloadType byte
- defaultCloseStatus int
-}
-
-// Read implements the io.Reader interface:
-// it reads data of a frame from the WebSocket connection.
-// if msg is not large enough for the frame data, it fills the msg and next Read
-// will read the rest of the frame data.
-// it reads Text frame or Binary frame.
-func (ws *Conn) Read(msg []byte) (n int, err error) {
- ws.rio.Lock()
- defer ws.rio.Unlock()
-again:
- if ws.frameReader == nil {
- frame, err := ws.frameReaderFactory.NewFrameReader()
- if err != nil {
- return 0, err
- }
- ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
- if err != nil {
- return 0, err
- }
- if ws.frameReader == nil {
- goto again
- }
- }
- n, err = ws.frameReader.Read(msg)
- if err == io.EOF {
- if trailer := ws.frameReader.TrailerReader(); trailer != nil {
- io.Copy(ioutil.Discard, trailer)
- }
- ws.frameReader = nil
- goto again
- }
- return n, err
-}
-
-// Write implements the io.Writer interface:
-// it writes data as a frame to the WebSocket connection.
-func (ws *Conn) Write(msg []byte) (n int, err error) {
- ws.wio.Lock()
- defer ws.wio.Unlock()
- w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
- if err != nil {
- return 0, err
- }
- n, err = w.Write(msg)
- w.Close()
- if err != nil {
- return n, err
- }
- return n, err
-}
-
-// Close implements the io.Closer interface.
-func (ws *Conn) Close() error {
- err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
- if err != nil {
- return err
- }
- return ws.rwc.Close()
-}
-
-func (ws *Conn) IsClientConn() bool { return ws.request == nil }
-func (ws *Conn) IsServerConn() bool { return ws.request != nil }
-
-// LocalAddr returns the WebSocket Origin for the connection for client, or
-// the WebSocket location for server.
-func (ws *Conn) LocalAddr() net.Addr {
- if ws.IsClientConn() {
- return &Addr{ws.config.Origin}
- }
- return &Addr{ws.config.Location}
-}
-
-// RemoteAddr returns the WebSocket location for the connection for client, or
-// the Websocket Origin for server.
-func (ws *Conn) RemoteAddr() net.Addr {
- if ws.IsClientConn() {
- return &Addr{ws.config.Location}
- }
- return &Addr{ws.config.Origin}
-}
-
-var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
-
-// SetDeadline sets the connection's network read & write deadlines.
-func (ws *Conn) SetDeadline(t time.Time) error {
- if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetDeadline(t)
- }
- return errSetDeadline
-}
-
-// SetReadDeadline sets the connection's network read deadline.
-func (ws *Conn) SetReadDeadline(t time.Time) error {
- if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetReadDeadline(t)
- }
- return errSetDeadline
-}
-
-// SetWriteDeadline sets the connection's network write deadline.
-func (ws *Conn) SetWriteDeadline(t time.Time) error {
- if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetWriteDeadline(t)
- }
- return errSetDeadline
-}
-
-// Config returns the WebSocket config.
-func (ws *Conn) Config() *Config { return ws.config }
-
-// Request returns the http request upgraded to the WebSocket.
-// It is nil for client side.
-func (ws *Conn) Request() *http.Request { return ws.request }
-
-// Codec represents a symmetric pair of functions that implement a codec.
-type Codec struct {
- Marshal func(v interface{}) (data []byte, payloadType byte, err error)
- Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
-}
-
-// Send sends v marshaled by cd.Marshal as single frame to ws.
-func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
- if err != nil {
- return err
- }
- data, payloadType, err := cd.Marshal(v)
- if err != nil {
- return err
- }
- ws.wio.Lock()
- defer ws.wio.Unlock()
- w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
- _, err = w.Write(data)
- w.Close()
- return err
-}
-
-// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
-func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
- ws.rio.Lock()
- defer ws.rio.Unlock()
- if ws.frameReader != nil {
- _, err = io.Copy(ioutil.Discard, ws.frameReader)
- if err != nil {
- return err
- }
- ws.frameReader = nil
- }
-again:
- frame, err := ws.frameReaderFactory.NewFrameReader()
- if err != nil {
- return err
- }
- frame, err = ws.frameHandler.HandleFrame(frame)
- if err != nil {
- return err
- }
- if frame == nil {
- goto again
- }
- payloadType := frame.PayloadType()
- data, err := ioutil.ReadAll(frame)
- if err != nil {
- return err
- }
- return cd.Unmarshal(data, payloadType, v)
-}
-
-func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
- switch data := v.(type) {
- case string:
- return []byte(data), TextFrame, nil
- case []byte:
- return data, BinaryFrame, nil
- }
- return nil, UnknownFrame, ErrNotSupported
-}
-
-func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
- switch data := v.(type) {
- case *string:
- *data = string(msg)
- return nil
- case *[]byte:
- *data = msg
- return nil
- }
- return ErrNotSupported
-}
-
-/*
-Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
-To send/receive text frame, use string type.
-To send/receive binary frame, use []byte type.
-
-Trivial usage:
-
- import "websocket"
-
- // receive text frame
- var message string
- websocket.Message.Receive(ws, &message)
-
- // send text frame
- message = "hello"
- websocket.Message.Send(ws, message)
-
- // receive binary frame
- var data []byte
- websocket.Message.Receive(ws, &data)
-
- // send binary frame
- data = []byte{0, 1, 2}
- websocket.Message.Send(ws, data)
-
-*/
-var Message = Codec{marshal, unmarshal}
-
-func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
- msg, err = json.Marshal(v)
- return msg, TextFrame, err
-}
-
-func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
- return json.Unmarshal(msg, v)
-}
-
-/*
-JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
-
-Trival usage:
-
- import "websocket"
-
- type T struct {
- Msg string
- Count int
- }
-
- // receive JSON type T
- var data T
- websocket.JSON.Receive(ws, &data)
-
- // send JSON type T
- websocket.JSON.Send(ws, data)
-*/
-var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/libgo/go/websocket/websocket_test.go b/libgo/go/websocket/websocket_test.go
deleted file mode 100644
index f41c355fac2..00000000000
--- a/libgo/go/websocket/websocket_test.go
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
- "bytes"
- "fmt"
- "io"
- "log"
- "net"
- "net/http"
- "net/http/httptest"
- "net/url"
- "strings"
- "sync"
- "testing"
-)
-
-var serverAddr string
-var once sync.Once
-
-func echoServer(ws *Conn) { io.Copy(ws, ws) }
-
-type Count struct {
- S string
- N int
-}
-
-func countServer(ws *Conn) {
- for {
- var count Count
- err := JSON.Receive(ws, &count)
- if err != nil {
- return
- }
- count.N++
- count.S = strings.Repeat(count.S, count.N)
- err = JSON.Send(ws, count)
- if err != nil {
- return
- }
- }
-}
-
-func startServer() {
- http.Handle("/echo", Handler(echoServer))
- http.Handle("/count", Handler(countServer))
- server := httptest.NewServer(nil)
- serverAddr = server.Listener.Addr().String()
- log.Print("Test WebSocket server listening on ", serverAddr)
-}
-
-func newConfig(t *testing.T, path string) *Config {
- config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
- return config
-}
-
-func TestEcho(t *testing.T) {
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/echo"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- msg := []byte("hello, world\n")
- if _, err := conn.Write(msg); err != nil {
- t.Errorf("Write: %v", err)
- }
- var actual_msg = make([]byte, 512)
- n, err := conn.Read(actual_msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- actual_msg = actual_msg[0:n]
- if !bytes.Equal(msg, actual_msg) {
- t.Errorf("Echo: expected %q got %q", msg, actual_msg)
- }
- conn.Close()
-}
-
-func TestAddr(t *testing.T) {
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/echo"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- ra := conn.RemoteAddr().String()
- if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
- t.Errorf("Bad remote addr: %v", ra)
- }
- la := conn.LocalAddr().String()
- if !strings.HasPrefix(la, "http://") {
- t.Errorf("Bad local addr: %v", la)
- }
- conn.Close()
-}
-
-func TestCount(t *testing.T) {
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/count"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- var count Count
- count.S = "hello"
- if err := JSON.Send(conn, count); err != nil {
- t.Errorf("Write: %v", err)
- }
- if err := JSON.Receive(conn, &count); err != nil {
- t.Errorf("Read: %v", err)
- }
- if count.N != 1 {
- t.Errorf("count: expected %d got %d", 1, count.N)
- }
- if count.S != "hello" {
- t.Errorf("count: expected %q got %q", "hello", count.S)
- }
- if err := JSON.Send(conn, count); err != nil {
- t.Errorf("Write: %v", err)
- }
- if err := JSON.Receive(conn, &count); err != nil {
- t.Errorf("Read: %v", err)
- }
- if count.N != 2 {
- t.Errorf("count: expected %d got %d", 2, count.N)
- }
- if count.S != "hellohello" {
- t.Errorf("count: expected %q got %q", "hellohello", count.S)
- }
- conn.Close()
-}
-
-func TestWithQuery(t *testing.T) {
- once.Do(startServer)
-
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
-
- config := newConfig(t, "/echo")
- config.Location, err = url.ParseRequest(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
- if err != nil {
- t.Fatal("location url", err)
- }
-
- ws, err := NewClient(config, client)
- if err != nil {
- t.Errorf("WebSocket handshake: %v", err)
- return
- }
- ws.Close()
-}
-
-func TestWithProtocol(t *testing.T) {
- once.Do(startServer)
-
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
-
- config := newConfig(t, "/echo")
- config.Protocol = append(config.Protocol, "test")
-
- ws, err := NewClient(config, client)
- if err != nil {
- t.Errorf("WebSocket handshake: %v", err)
- return
- }
- ws.Close()
-}
-
-func TestHTTP(t *testing.T) {
- once.Do(startServer)
-
- // If the client did not send a handshake that matches the protocol
- // specification, the server MUST return an HTTP respose with an
- // appropriate error code (such as 400 Bad Request)
- resp, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
- if err != nil {
- t.Errorf("Get: error %#v", err)
- return
- }
- if resp == nil {
- t.Error("Get: resp is null")
- return
- }
- if resp.StatusCode != http.StatusBadRequest {
- t.Errorf("Get: expected %q got %q", http.StatusBadRequest, resp.StatusCode)
- }
-}
-
-func TestTrailingSpaces(t *testing.T) {
- // http://code.google.com/p/go/issues/detail?id=955
- // The last runs of this create keys with trailing spaces that should not be
- // generated by the client.
- once.Do(startServer)
- config := newConfig(t, "/echo")
- for i := 0; i < 30; i++ {
- // body
- ws, err := DialConfig(config)
- if err != nil {
- t.Errorf("Dial #%d failed: %v", i, err)
- break
- }
- ws.Close()
- }
-}
-
-func TestSmallBuffer(t *testing.T) {
- // http://code.google.com/p/go/issues/detail?id=1145
- // Read should be able to handle reading a fragment of a frame.
- once.Do(startServer)
-
- // websocket.Dial()
- client, err := net.Dial("tcp", serverAddr)
- if err != nil {
- t.Fatal("dialing", err)
- }
- conn, err := NewClient(newConfig(t, "/echo"), client)
- if err != nil {
- t.Errorf("WebSocket handshake error: %v", err)
- return
- }
-
- msg := []byte("hello, world\n")
- if _, err := conn.Write(msg); err != nil {
- t.Errorf("Write: %v", err)
- }
- var small_msg = make([]byte, 8)
- n, err := conn.Read(small_msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- if !bytes.Equal(msg[:len(small_msg)], small_msg) {
- t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
- }
- var second_msg = make([]byte, len(msg))
- n, err = conn.Read(second_msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- second_msg = second_msg[0:n]
- if !bytes.Equal(msg[len(small_msg):], second_msg) {
- t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
- }
- conn.Close()
-}