summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorserg@serg.mylan <>2005-05-14 19:28:29 +0200
committerserg@serg.mylan <>2005-05-14 19:28:29 +0200
commit40ce1e174d1e02b9e11a6092a332ca74280e040d (patch)
treeef2346baa5a2fe4cff6f083464efec28e5ea3c34
parent0dab212f5c1dcf6d829751765ae9d5dcdb5346d5 (diff)
parent7cb3e5924c6064e31542332a48f81c9f87928ed8 (diff)
downloadmariadb-git-40ce1e174d1e02b9e11a6092a332ca74280e040d.tar.gz
merged
-rw-r--r--BUILD/FINISH.sh6
-rw-r--r--BUILD/Makefile.am1
-rwxr-xr-xBUILD/check-cpu32
-rwxr-xr-xBUILD/compile-darwin-mwcc54
-rwxr-xr-xBUILD/compile-dist5
-rwxr-xr-xBUILD/compile-pentium-debug-yassl13
-rw-r--r--BitKeeper/etc/config1
-rw-r--r--BitKeeper/etc/logging_ok14
-rw-r--r--Makefile.am7
-rw-r--r--client/Makefile.am4
-rw-r--r--client/client_priv.h7
-rw-r--r--client/mysql.cc18
-rw-r--r--client/mysqladmin.cc5
-rw-r--r--client/mysqlbinlog.cc1
-rw-r--r--client/mysqldump.c19
-rw-r--r--client/mysqlshow.c65
-rw-r--r--cmd-line-utils/libedit/Makefile.am4
-rw-r--r--cmd-line-utils/libedit/config.h2
-rw-r--r--cmd-line-utils/readline/terminal.c2
-rw-r--r--config/ac-macros/misc.m421
-rw-r--r--config/ac-macros/yassl.m433
-rw-r--r--configure.in93
-rw-r--r--extra/Makefile.am1
-rw-r--r--extra/my_print_defaults.c14
-rw-r--r--extra/yassl/AUTHORS0
-rw-r--r--extra/yassl/ChangeLog0
-rw-r--r--extra/yassl/INSTALL229
-rw-r--r--extra/yassl/Makefile.am2
-rw-r--r--extra/yassl/NEWS0
-rw-r--r--extra/yassl/README263
-rw-r--r--extra/yassl/include/buffer.hpp207
-rw-r--r--extra/yassl/include/cert_wrapper.hpp124
-rw-r--r--extra/yassl/include/crypto_wrapper.hpp418
-rw-r--r--extra/yassl/include/factory.hpp106
-rw-r--r--extra/yassl/include/handshake.hpp72
-rw-r--r--extra/yassl/include/lock.hpp90
-rw-r--r--extra/yassl/include/log.hpp58
-rw-r--r--extra/yassl/include/openssl/crypto.h13
-rw-r--r--extra/yassl/include/openssl/des.h1
-rw-r--r--extra/yassl/include/openssl/err.h8
-rw-r--r--extra/yassl/include/openssl/lhash.h2
-rw-r--r--extra/yassl/include/openssl/md5.h1
-rw-r--r--extra/yassl/include/openssl/opensslv.h12
-rw-r--r--extra/yassl/include/openssl/rand.h2
-rw-r--r--extra/yassl/include/openssl/rsa.h10
-rw-r--r--extra/yassl/include/openssl/ssl.h400
-rw-r--r--extra/yassl/include/socket_wrapper.hpp95
-rw-r--r--extra/yassl/include/timer.hpp43
-rw-r--r--extra/yassl/include/yassl_error.hpp78
-rw-r--r--extra/yassl/include/yassl_imp.hpp742
-rw-r--r--extra/yassl/include/yassl_int.hpp540
-rw-r--r--extra/yassl/include/yassl_types.hpp415
-rw-r--r--extra/yassl/mySTL/algorithm.hpp111
-rw-r--r--extra/yassl/mySTL/helpers.hpp94
-rw-r--r--extra/yassl/mySTL/list.hpp374
-rw-r--r--extra/yassl/mySTL/memory.hpp127
-rw-r--r--extra/yassl/mySTL/pair.hpp61
-rw-r--r--extra/yassl/mySTL/stdexcept.hpp72
-rw-r--r--extra/yassl/mySTL/vector.hpp154
-rw-r--r--extra/yassl/src/Makefile.am7
-rw-r--r--extra/yassl/src/buffer.cpp280
-rw-r--r--extra/yassl/src/cert_wrapper.cpp318
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp978
-rw-r--r--extra/yassl/src/handshake.cpp1011
-rw-r--r--extra/yassl/src/lock.cpp90
-rw-r--r--extra/yassl/src/log.cpp148
-rw-r--r--extra/yassl/src/socket_wrapper.cpp168
-rw-r--r--extra/yassl/src/ssl.cpp1039
-rw-r--r--extra/yassl/src/timer.cpp82
-rw-r--r--extra/yassl/src/yassl_error.cpp53
-rw-r--r--extra/yassl/src/yassl_imp.cpp2118
-rw-r--r--extra/yassl/src/yassl_int.cpp1976
-rw-r--r--extra/yassl/taocrypt/Makefile.am2
-rw-r--r--extra/yassl/taocrypt/include/aes.hpp89
-rw-r--r--extra/yassl/taocrypt/include/algebra.hpp316
-rw-r--r--extra/yassl/taocrypt/include/arc4.hpp59
-rw-r--r--extra/yassl/taocrypt/include/asn.hpp327
-rw-r--r--extra/yassl/taocrypt/include/block.hpp211
-rw-r--r--extra/yassl/taocrypt/include/coding.hpp94
-rw-r--r--extra/yassl/taocrypt/include/des.hpp121
-rw-r--r--extra/yassl/taocrypt/include/dh.hpp89
-rw-r--r--extra/yassl/taocrypt/include/dsa.hpp129
-rw-r--r--extra/yassl/taocrypt/include/error.hpp86
-rw-r--r--extra/yassl/taocrypt/include/file.hpp124
-rw-r--r--extra/yassl/taocrypt/include/hash.hpp73
-rw-r--r--extra/yassl/taocrypt/include/hmac.hpp128
-rw-r--r--extra/yassl/taocrypt/include/integer.hpp324
-rw-r--r--extra/yassl/taocrypt/include/md2.hpp67
-rw-r--r--extra/yassl/taocrypt/include/md5.hpp63
-rw-r--r--extra/yassl/taocrypt/include/misc.hpp776
-rw-r--r--extra/yassl/taocrypt/include/modarith.hpp169
-rw-r--r--extra/yassl/taocrypt/include/modes.hpp133
-rw-r--r--extra/yassl/taocrypt/include/random.hpp87
-rw-r--r--extra/yassl/taocrypt/include/ripemd.hpp63
-rw-r--r--extra/yassl/taocrypt/include/rsa.hpp253
-rw-r--r--extra/yassl/taocrypt/include/runtime.hpp72
-rw-r--r--extra/yassl/taocrypt/include/sha.hpp65
-rw-r--r--extra/yassl/taocrypt/src/Makefile.am7
-rw-r--r--extra/yassl/taocrypt/src/aes.cpp401
-rw-r--r--extra/yassl/taocrypt/src/aestables.cpp724
-rw-r--r--extra/yassl/taocrypt/src/algebra.cpp354
-rw-r--r--extra/yassl/taocrypt/src/arc4.cpp93
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp1051
-rw-r--r--extra/yassl/taocrypt/src/coding.cpp250
-rw-r--r--extra/yassl/taocrypt/src/des.cpp435
-rw-r--r--extra/yassl/taocrypt/src/dh.cpp85
-rw-r--r--extra/yassl/taocrypt/src/dsa.cpp277
-rw-r--r--extra/yassl/taocrypt/src/file.cpp118
-rw-r--r--extra/yassl/taocrypt/src/hash.cpp88
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp4181
-rw-r--r--extra/yassl/taocrypt/src/md2.cpp128
-rw-r--r--extra/yassl/taocrypt/src/md5.cpp169
-rw-r--r--extra/yassl/taocrypt/src/misc.cpp132
-rw-r--r--extra/yassl/taocrypt/src/random.cpp131
-rw-r--r--extra/yassl/taocrypt/src/ripemd.cpp289
-rw-r--r--extra/yassl/taocrypt/src/rsa.cpp238
-rw-r--r--extra/yassl/taocrypt/src/sha.cpp144
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsp260
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsw44
-rw-r--r--extra/yassl/yassl.dsp192
-rw-r--r--extra/yassl/yassl.dsw137
-rw-r--r--heap/hp_hash.c13
-rw-r--r--include/config-win.h17
-rw-r--r--include/decimal.h2
-rw-r--r--include/errmsg.h3
-rw-r--r--include/m_ctype.h5
-rw-r--r--include/my_global.h36
-rw-r--r--include/my_handler.h5
-rw-r--r--include/my_sys.h6
-rw-r--r--include/raid.h2
-rw-r--r--include/violite.h7
-rw-r--r--innobase/include/lock0lock.h11
-rw-r--r--innobase/include/srv0srv.h9
-rw-r--r--innobase/lock/lock0lock.c35
-rw-r--r--innobase/srv/srv0srv.c29
-rw-r--r--libmysql/errmsg.c3
-rw-r--r--libmysql/libmysql.c120
-rw-r--r--libmysql/libmysql.def3
-rw-r--r--libmysqld/emb_qcache.cc36
-rw-r--r--libmysqld/emb_qcache.h27
-rw-r--r--libmysqld/libmysqld.c13
-rw-r--r--myisam/myisampack.c9
-rw-r--r--myisammrg/myrg_open.c2
-rw-r--r--mysql-test/mysql-test-run.sh9
-rw-r--r--mysql-test/r/bigint.result17
-rw-r--r--mysql-test/r/blackhole.result8
-rw-r--r--mysql-test/r/case.result10
-rw-r--r--mysql-test/r/cast.result73
-rw-r--r--mysql-test/r/check.result9
-rw-r--r--mysql-test/r/create.result27
-rw-r--r--mysql-test/r/ctype_latin1_de.result6
-rw-r--r--mysql-test/r/ctype_latin2.result383
-rw-r--r--mysql-test/r/ctype_utf8.result3
-rw-r--r--mysql-test/r/distinct.result2
-rw-r--r--mysql-test/r/func_group.result54
-rw-r--r--mysql-test/r/func_op.result2
-rw-r--r--mysql-test/r/gis-rtree.result2
-rw-r--r--mysql-test/r/gis.result14
-rw-r--r--mysql-test/r/group_by.result8
-rw-r--r--mysql-test/r/group_min_max.result7
-rw-r--r--mysql-test/r/information_schema.result42
-rw-r--r--mysql-test/r/information_schema_db.result28
-rw-r--r--mysql-test/r/innodb-replace.result1
-rw-r--r--mysql-test/r/innodb.result6
-rw-r--r--mysql-test/r/insert_update.result13
-rw-r--r--mysql-test/r/join_outer.result14
-rw-r--r--mysql-test/r/lowercase_table.result3
-rw-r--r--mysql-test/r/metadata.result4
-rw-r--r--mysql-test/r/mysqldump.result60
-rw-r--r--mysql-test/r/ndb_restore.result1
-rw-r--r--mysql-test/r/olap.result26
-rw-r--r--mysql-test/r/ps.result63
-rw-r--r--mysql-test/r/ps_2myisam.result258
-rw-r--r--mysql-test/r/ps_3innodb.result258
-rw-r--r--mysql-test/r/ps_4heap.result258
-rw-r--r--mysql-test/r/ps_5merge.result516
-rw-r--r--mysql-test/r/ps_6bdb.result258
-rw-r--r--mysql-test/r/ps_7ndb.result258
-rw-r--r--mysql-test/r/query_cache.result27
-rw-r--r--mysql-test/r/rpl_sp.result258
-rw-r--r--mysql-test/r/select.result35
-rw-r--r--mysql-test/r/sp.result69
-rw-r--r--mysql-test/r/strict.result5
-rw-r--r--mysql-test/r/system_mysql_db.result3
-rw-r--r--mysql-test/r/temp_table.result9
-rw-r--r--mysql-test/r/type_bit.result21
-rw-r--r--mysql-test/r/type_blob.result2
-rw-r--r--mysql-test/r/type_datetime.result2
-rw-r--r--mysql-test/r/type_decimal.result2
-rw-r--r--mysql-test/r/type_float.result2
-rw-r--r--mysql-test/r/type_newdecimal.result105
-rw-r--r--mysql-test/r/type_ranges.result2
-rw-r--r--mysql-test/r/union.result4
-rw-r--r--mysql-test/r/user_limits.result4
-rw-r--r--mysql-test/r/user_var.result41
-rw-r--r--mysql-test/r/variables.result2
-rw-r--r--mysql-test/r/view.result40
-rw-r--r--mysql-test/t/archive.test2
-rw-r--r--mysql-test/t/bigint.test10
-rw-r--r--mysql-test/t/cast.test26
-rw-r--r--mysql-test/t/check.test12
-rw-r--r--mysql-test/t/create.test11
-rw-r--r--mysql-test/t/ctype_latin1_de.test8
-rw-r--r--mysql-test/t/ctype_latin2.test50
-rw-r--r--mysql-test/t/ctype_utf8.test6
-rw-r--r--mysql-test/t/func_group.test4
-rw-r--r--mysql-test/t/gis-rtree.test2
-rw-r--r--mysql-test/t/gis.test16
-rw-r--r--mysql-test/t/group_min_max.test11
-rw-r--r--mysql-test/t/information_schema.test41
-rw-r--r--mysql-test/t/information_schema_db.test9
-rw-r--r--mysql-test/t/innodb-replace.test4
-rw-r--r--mysql-test/t/innodb.test9
-rw-r--r--mysql-test/t/insert_update.test12
-rw-r--r--mysql-test/t/join_outer.test15
-rw-r--r--mysql-test/t/lowercase_table.test8
-rw-r--r--mysql-test/t/mysqldump.test11
-rw-r--r--mysql-test/t/ndb_restore.test6
-rw-r--r--mysql-test/t/olap.test5
-rw-r--r--mysql-test/t/ps.test74
-rw-r--r--mysql-test/t/query_cache.test45
-rw-r--r--mysql-test/t/range.test4
-rw-r--r--mysql-test/t/rpl_sp-master.opt1
-rw-r--r--mysql-test/t/rpl_sp-slave.opt1
-rw-r--r--mysql-test/t/rpl_sp.test266
-rw-r--r--mysql-test/t/select.test43
-rw-r--r--mysql-test/t/sp.test83
-rw-r--r--mysql-test/t/strict.test10
-rw-r--r--mysql-test/t/temp_table-master.opt1
-rw-r--r--mysql-test/t/temp_table.test8
-rw-r--r--mysql-test/t/type_bit.test22
-rw-r--r--mysql-test/t/type_decimal.test2
-rw-r--r--mysql-test/t/type_newdecimal.test47
-rw-r--r--mysql-test/t/user_var.test26
-rw-r--r--mysql-test/t/view.test22
-rw-r--r--mysql-test/valgrind.supp40
-rw-r--r--mysys/default.c260
-rw-r--r--mysys/mf_keycache.c11
-rw-r--r--mysys/my_getwd.c22
-rw-r--r--mysys/my_new.cc9
-rw-r--r--mysys/my_thr_init.c11
-rw-r--r--ndb/src/common/portlib/gcc.cpp2
-rw-r--r--ndb/src/common/util/new.cpp2
-rw-r--r--ndb/src/cw/cpcd/APIService.cpp1
-rw-r--r--ndb/src/cw/cpcd/CPCD.hpp6
-rw-r--r--ndb/src/cw/cpcd/Process.cpp14
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp30
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcInit.cpp4
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp88
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp2
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp4
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp10
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp6
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp13
-rw-r--r--ndb/src/ndbapi/ClusterMgr.hpp14
-rw-r--r--ndb/src/ndbapi/Ndb.cpp11
-rw-r--r--ndb/src/ndbapi/ndberror.c2
-rw-r--r--ndb/test/include/CpcClient.hpp1
-rw-r--r--ndb/test/ndbapi/testNodeRestart.cpp2
-rw-r--r--ndb/test/run-test/Makefile.am7
-rw-r--r--ndb/test/run-test/conf-daily-basic-dl145a.txt19
-rw-r--r--ndb/test/run-test/conf-daily-basic-ndbmaster.txt19
-rw-r--r--ndb/test/run-test/conf-daily-basic-shark.txt19
-rw-r--r--ndb/test/run-test/conf-daily-devel-ndbmaster.txt19
-rw-r--r--ndb/test/run-test/conf-daily-sql-ndbmaster.txt20
-rw-r--r--ndb/test/run-test/main.cpp43
-rwxr-xr-xndb/test/run-test/make-config.sh526
-rwxr-xr-xndb/test/run-test/ndb-autotest.sh78
-rw-r--r--ndb/test/run-test/run-test.hpp1
-rw-r--r--ndb/test/src/CpcClient.cpp3
-rw-r--r--ndb/test/src/NDBT_ResultRow.cpp8
-rw-r--r--scripts/make_binary_distribution.sh29
-rw-r--r--scripts/mysql_create_system_tables.sh3
-rw-r--r--scripts/mysql_fix_privilege_tables.sql4
-rw-r--r--scripts/mysql_install_db.sh5
-rw-r--r--server-tools/instance-manager/command.cc3
-rw-r--r--sql-common/client.c2
-rw-r--r--sql/examples/ha_archive.h2
-rw-r--r--sql/examples/ha_example.h2
-rw-r--r--sql/field.cc129
-rw-r--r--sql/field.h28
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_berkeley.h3
-rw-r--r--sql/ha_blackhole.cc4
-rw-r--r--sql/ha_blackhole.h2
-rw-r--r--sql/ha_heap.cc6
-rw-r--r--sql/ha_heap.h2
-rw-r--r--sql/ha_innodb.cc82
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/ha_myisam.h2
-rw-r--r--sql/ha_myisammrg.cc28
-rw-r--r--sql/ha_myisammrg.h2
-rw-r--r--sql/ha_ndbcluster.cc45
-rw-r--r--sql/ha_ndbcluster.h2
-rw-r--r--sql/handler.cc35
-rw-r--r--sql/handler.h2
-rw-r--r--sql/hostname.cc21
-rw-r--r--sql/item.cc310
-rw-r--r--sql/item.h78
-rw-r--r--sql/item_cmpfunc.cc34
-rw-r--r--sql/item_cmpfunc.h12
-rw-r--r--sql/item_func.cc425
-rw-r--r--sql/item_func.h21
-rw-r--r--sql/item_geofunc.cc7
-rw-r--r--sql/item_geofunc.h2
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/item_strfunc.h2
-rw-r--r--sql/item_subselect.h5
-rw-r--r--sql/item_sum.cc101
-rw-r--r--sql/item_sum.h18
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/key.cc6
-rw-r--r--sql/log.cc8
-rw-r--r--sql/log_event.cc62
-rw-r--r--sql/log_event.h5
-rw-r--r--sql/my_decimal.cc26
-rw-r--r--sql/my_decimal.h46
-rw-r--r--sql/mysql_priv.h10
-rw-r--r--sql/mysqld.cc83
-rw-r--r--sql/net_serv.cc4
-rw-r--r--sql/opt_range.cc51
-rw-r--r--sql/opt_range.h8
-rw-r--r--sql/opt_sum.cc10
-rw-r--r--sql/procedure.h2
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/protocol.h2
-rw-r--r--sql/set_var.cc9
-rw-r--r--sql/set_var.h2
-rw-r--r--sql/share/charsets/Index.xml3
-rw-r--r--sql/share/charsets/cp1250.xml25
-rw-r--r--sql/share/charsets/latin2.xml36
-rw-r--r--sql/share/errmsg.txt20
-rw-r--r--sql/slave.cc26
-rw-r--r--sql/sp.cc42
-rw-r--r--sql/sp_head.cc93
-rw-r--r--sql/sp_rcontext.cc6
-rw-r--r--sql/sp_rcontext.h10
-rw-r--r--sql/spatial.cc2
-rw-r--r--sql/spatial.h2
-rw-r--r--sql/sql_acl.cc59
-rw-r--r--sql/sql_base.cc21
-rw-r--r--sql/sql_bitmap.h2
-rw-r--r--sql/sql_cache.cc5
-rw-r--r--sql/sql_class.cc7
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_insert.cc16
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_parse.cc88
-rw-r--r--sql/sql_prepare.cc35
-rw-r--r--sql/sql_select.cc818
-rw-r--r--sql/sql_select.h24
-rw-r--r--sql/sql_show.cc120
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_table.cc136
-rw-r--r--sql/sql_test.cc2
-rw-r--r--sql/sql_trigger.cc28
-rw-r--r--sql/sql_trigger.h8
-rw-r--r--sql/sql_udf.h3
-rw-r--r--sql/sql_update.cc14
-rw-r--r--sql/sql_view.cc33
-rw-r--r--sql/sql_yacc.yy29
-rw-r--r--sql/table.cc45
-rw-r--r--sql/table.h7
-rw-r--r--sql/tztime.h2
-rw-r--r--sql/unireg.cc29
-rw-r--r--strings/ctype-big5.c3
-rw-r--r--strings/ctype-bin.c6
-rw-r--r--strings/ctype-cp932.c1
-rw-r--r--strings/ctype-czech.c1
-rw-r--r--strings/ctype-euc_kr.c1
-rw-r--r--strings/ctype-eucjpms.c1
-rw-r--r--strings/ctype-gb2312.c1
-rw-r--r--strings/ctype-gbk.c1
-rw-r--r--strings/ctype-latin1.c3
-rw-r--r--strings/ctype-mb.c3
-rw-r--r--strings/ctype-simple.c57
-rw-r--r--strings/ctype-sjis.c3
-rw-r--r--strings/ctype-tis620.c1
-rw-r--r--strings/ctype-uca.c6
-rw-r--r--strings/ctype-ucs2.c6
-rw-r--r--strings/ctype-ujis.c1
-rw-r--r--strings/ctype-utf8.c6
-rw-r--r--strings/ctype-win1250ch.c3
-rw-r--r--strings/decimal.c100
-rwxr-xr-xsupport-files/MacOSX/mwar-wrapper16
-rwxr-xr-xsupport-files/MacOSX/mwcc-wrapper48
-rw-r--r--support-files/mysql.server.sh2
-rwxr-xr-xtests/index_corrupt.pl212
-rw-r--r--tests/mysql_client_test.c311
-rw-r--r--vio/vio_priv.h4
-rw-r--r--vio/viosocket.c8
-rw-r--r--vio/viossl.c3
395 files changed, 34540 insertions, 3330 deletions
diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh
index 81defaa7f52..01e58b0ee1c 100644
--- a/BUILD/FINISH.sh
+++ b/BUILD/FINISH.sh
@@ -2,12 +2,6 @@ cflags="$c_warnings $extra_flags"
cxxflags="$cxx_warnings $base_cxxflags $extra_flags"
extra_configs="$extra_configs $local_infile_configs"
configure="./configure $base_configs $extra_configs"
-for arg
-do
- # Escape special characters so they don't confuse eval
- configure="$configure "`echo "$arg" | \
- sed -e 's,\([^a-zA-Z0-9_.=-]\),\\\\\1,g'`
-done
commands="\
$make -k distclean || true
diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am
index 9f3c55c20d5..d60672e05f8 100644
--- a/BUILD/Makefile.am
+++ b/BUILD/Makefile.am
@@ -29,6 +29,7 @@ EXTRA_DIST = FINISH.sh \
compile-pentium-debug-max \
compile-pentium-debug-no-bdb \
compile-pentium-debug-openssl \
+ compile-pentium-debug-yassl \
compile-pentium-gcov \
compile-pentium-gprof \
compile-pentium-max \
diff --git a/BUILD/check-cpu b/BUILD/check-cpu
index 553df39191f..3cce4b1ab3d 100755
--- a/BUILD/check-cpu
+++ b/BUILD/check-cpu
@@ -19,8 +19,23 @@ if test -r /proc/cpuinfo ; then
if test -z "$model_name" ; then
model_name=`uname -m`
fi
+else
+ # Fallback when there is no /proc/cpuinfo
+ case "`uname -s`" in
+ FreeBSD)
+ cpu_family=`uname -m`;
+ model_name=`sysctl -b hw.model`
+ ;;
+ *)
+ cpu_family=`uname -m`;
+ model_name="unknown";
+ ;;
+ esac
fi
+cpu_flag=""
+cpu_flag_old=""
+
case "$cpu_family--$model_name" in
Alpha*EV6*)
cpu_flag="ev6";
@@ -28,11 +43,24 @@ case "$cpu_family--$model_name" in
*Xeon*)
cpu_flag="nocona";
;;
+ *Pentium*4*Mobile*CPU*)
+ cpu_flag="pentium4m";
+ ;;
*Pentium*4*CPU*)
cpu_flag="pentium4";
;;
+ *Pentium*III*Mobile*CPU*)
+ cpu_flag="pentium3m";
+ ;;
+ *Pentium*III*CPU*)
+ cpu_flag="pentium3";
+ ;;
+ *Pentium*M*pro*)
+ cpu_flag="pentium-m";
+ ;;
*Athlon*64*)
cpu_flag="athlon64";
+ cpu_flag_old="athlon";
;;
*Athlon*)
cpu_flag="athlon";
@@ -72,6 +100,10 @@ case "$cc_ver--$cc_verno" in
check_cpu_cflags="-mtune=$cpu_flag -march=$cpu_flag"
;;
*GCC*)
+ # Fix for older compiler versions
+ if test -n "$cpu_flag_old"; then
+ cpu_flag="$cpu_flag_old"
+ fi
check_cpu_cflags="-mcpu=$cpu_flag -march=$cpu_flag"
;;
*)
diff --git a/BUILD/compile-darwin-mwcc b/BUILD/compile-darwin-mwcc
new file mode 100755
index 00000000000..6fd0eab7e26
--- /dev/null
+++ b/BUILD/compile-darwin-mwcc
@@ -0,0 +1,54 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+c_warnings=""
+cxx_warnings=""
+fast_cflags="-O3"
+base_cxxflags="-fno-handle-exceptions"
+
+# FIXME do we need to link static, not to depend on CodeWarrior libs?
+
+if [ x$MODE = x ] ; then
+ echo "You need to give an argument, 'standard', 'max', 'debug' or 'debug-max'"
+ echo "Like: MODE=standard BUILD/compile-darwin-codewarrior"
+ exit 1
+else
+ case $MODE in
+ standard|pro-gpl)
+ # FIXME pro/pro-gpl different libedit/readline
+ extra_flags="$ppc_cflags $fast_cflags"
+ ;;
+ pro)
+ # FIXME pro/pro-gpl different libedit/readline
+ extra_flags="$ppc_cflags $fast_cflags"
+ extra_configs="--with-libedit"
+ ;;
+ max)
+ extra_flags="$ppc_cflags $fast_cflags"
+ extra_configs="$max_configs"
+ ;;
+ debug)
+ extra_flags="$ppc_cflags $debug_cflags"
+ c_warnings="$c_warnings $debug_extra_warnings"
+ cxx_warnings="$cxx_warnings $debug_extra_warnings"
+ extra_configs="$debug_configs"
+ ;;
+ debug-max)
+ extra_flags="$ppc_cflags $debug_cflags $max_cflags"
+ c_warnings="$c_warnings $debug_extra_warnings"
+ cxx_warnings="$cxx_warnings $debug_extra_warnings"
+ extra_configs="$debug_configs $max_configs"
+ ;;
+ *)
+ echo "You need to give an argument, 'standard', 'max', 'debug' or 'debug-max'"
+ echo "Like: MODE=standard BUILD/compile-darwin-codewarrior"
+ exit 1
+ ;;
+ esac
+fi
+
+extra_configs="$extra_configs --with-darwin-mwcc"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-dist b/BUILD/compile-dist
index 7c177f54258..39095f59ffa 100755
--- a/BUILD/compile-dist
+++ b/BUILD/compile-dist
@@ -18,12 +18,17 @@ autoconf
# Default to gcc for CC and CXX
if test -z "$CXX" ; then
export CXX=gcc
+ # Set some required compile options
+ if test -z "$CXXFLAGS" ; then
+ export CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti"
+ fi
fi
if test -z "$CC" ; then
export CC=gcc
fi
+
# Use ccache, if available
if ccache -V > /dev/null 2>&1
then
diff --git a/BUILD/compile-pentium-debug-yassl b/BUILD/compile-pentium-debug-yassl
new file mode 100755
index 00000000000..666e73d0267
--- /dev/null
+++ b/BUILD/compile-pentium-debug-yassl
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $debug_cflags"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs"
+
+extra_configs="$extra_configs --with-debug=full --with-yassl"
+
+. "$path/FINISH.sh"
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index c609fcdbd49..1ac24031dca 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -69,6 +69,7 @@ pager:
hours:
[serg:]checkout:get
[arjen:]checkout:get
+[kostja:]checkout:get
[nick:]checkout:get
checkout:edit
eoln:unix
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index d0af9545aef..5b43d25b818 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -15,6 +15,7 @@ ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
akishkin@work.mysql.com
anjuta@arthur.local
antony@ltantony.dsl-verizon.net
+antony@ltantony.mysql.com
antony@ltantony.rdg.cyberkinetica.com
antony@ltantony.rdg.cyberkinetica.homeunix.net
arjen@bitbike.com
@@ -32,6 +33,7 @@ bar@mysql.com
bar@noter.intranet.mysql.r18.ru
bell@51.0.168.192.in-addr.arpa
bell@52.0.168.192.in-addr.arpa
+bell@book.sanja.is.com.ua
bell@laptop.sanja.is.com.ua
bell@sanja.is.com.ua
bk@admin.bk
@@ -50,6 +52,8 @@ dlenev@build.mysql.com
dlenev@jabberwock.localdomain
dlenev@mysql.com
ejonore@mc03.ndb.mysql.com
+evgen@moonbone.(none)
+evgen@moonbone.local
gbichot@production.mysql.com
gbichot@quadita2.mysql.com
gbichot@quadxeon.mysql.com
@@ -80,6 +84,7 @@ hf@bisonxp.(none)
hf@deer.(none)
hf@deer.mysql.r18.ru
hf@genie.(none)
+holyfoot@mysql.com
igor@hundin.mysql.fi
igor@linux.local
igor@rurik.mysql.com
@@ -94,6 +99,7 @@ jani@dsl-jkl1657.dial.inet.fi
jani@dsl-kpogw4gb5.dial.inet.fi
jani@hynda.(none)
jani@hynda.mysql.fi
+jani@ibmlab.site
jani@janikt.pp.saunalahti.fi
jani@linux.local
jani@rhols221.adsl.netsonic.fi
@@ -110,6 +116,7 @@ jcole@sarvik.tfr.cafe.ee
jcole@tetra.spaceapes.com
jimw@mysql.com
joerg@mysql.com
+joerg@trift-lap.fambruehe
jon@gigan.
jonas@mysql.com
joreland@bk-internal.mysql.com
@@ -120,6 +127,7 @@ kaa@polly.local
kaj@work.mysql.com
kent@mysql.com
konstantin@mysql.com
+kosipov@production.mysql.com
kostja@oak.local
lars@mysql.com
lenz@kallisto.mysql.com
@@ -175,6 +183,7 @@ mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@here.mwagner.org
mwagner@mysql.com
+mwagner@ultrafly.mysql.com
mwagner@work.mysql.com
mydev@mysql.com
mysql@home.(none)
@@ -184,6 +193,7 @@ mysqldev@build.mysql2.com
mysqldev@melody.local
mysqldev@mysql.com
mysqldev@o2k.irixworld.net
+ndbdev@dl145b.mysql.com
ndbdev@eel.hemma.oreland.se
ndbdev@ndbmaster.mysql.com
ndbdev@shark.
@@ -216,9 +226,11 @@ ram@deer.(none)
ram@gw.mysql.r18.ru
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
+ram@ram-book.(none)
ram@ram.(none)
ramil@mysql.com
ranger@regul.home.lan
+rburnett@bk-internal.mysql.com
rburnett@build.mysql.com
reggie@bob.(none)
reggie@mdk10.(none)
@@ -239,6 +251,7 @@ serg@serg.mysql.com
serg@sergbook.mylan
serg@sergbook.mysql.com
sergefp@mysql.com
+shuichi@mysql.com
sinisa@rhols221.adsl.netsonic.fi
stewart@mysql.com
svoj@mysql.com
@@ -266,6 +279,7 @@ tonu@x153.internalnet
tonu@x3.internalnet
tsmith@build.mysql.com
tulin@build.mysql.com
+tulin@dl145b.mysql.com
tulin@mysql.com
ulli@morbus.(none)
venu@hundin.mysql.fi
diff --git a/Makefile.am b/Makefile.am
index 78efd47b762..eec27484710 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@ AUTOMAKE_OPTIONS = foreign
# These are built from source in the Docs directory
EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT
-SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
+SUBDIRS = . include @docs_dirs@ @zlib_dir@ @yassl_dir@ \
@readline_topdir@ sql-common \
@thread_dirs@ pstack \
@sql_union_dirs@ scripts man tests \
@@ -102,5 +102,10 @@ tags:
test:
cd mysql-test; ./mysql-test-run && ./mysql-test-run --ps-protocol
+test-force:
+ cd mysql-test; \
+ mysql-test-run --force ;\
+ mysql-test-run --ps-protocol --force
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/client/Makefile.am b/client/Makefile.am
index 58dcebfd852..791da2760a5 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -30,10 +30,10 @@ noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
mysqladmin_SOURCES = mysqladmin.cc
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
-mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c
mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD)
-mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c
+mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c $(top_srcdir)/mysys/my_new.cc
+mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
mysqltestmanagerc_SOURCES = mysqlmanagerc.c
mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
diff --git a/client/client_priv.h b/client/client_priv.h
index 892a9185ffa..d656e54a2b8 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -45,10 +45,9 @@ enum options_client
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS,
OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
- OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY
+ OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT,
#ifdef HAVE_NDBCLUSTER_DB
- ,OPT_NDBCLUSTER,OPT_NDB_CONNECTSTRING
+ OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
#endif
- ,OPT_IGNORE_TABLE
- ,OPT_SHOW_WARNINGS
+ OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS
};
diff --git a/client/mysql.cc b/client/mysql.cc
index c3a5da430ac..15917e99a23 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -720,9 +720,15 @@ static void usage(int version)
const char* readline= "readline";
#endif
+#ifdef HAVE_READLINE
printf("%s Ver %s Distrib %s, for %s (%s) using %s %s\n",
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
readline, rl_library_version);
+#else
+ printf("%s Ver %s Distrib %s, for %s (%s)", my_progname, VER,
+ MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
+#endif
+
if (version)
return;
printf("\
@@ -966,7 +972,8 @@ static int read_lines(bool execute_commands)
}
else
{
- char *prompt= (char*) (glob_buffer.is_empty() ? construct_prompt() :
+ char *prompt= (char*) (ml_comment ? " /*> " :
+ glob_buffer.is_empty() ? construct_prompt() :
!in_string ? " -> " :
in_string == '\'' ?
" '> " : (in_string == '`' ?
@@ -1103,6 +1110,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
uchar inchar;
char buff[80], *pos, *out;
COMMANDS *com;
+ bool need_space= 0;
if (!line[0] && buffer.is_empty())
return 0;
@@ -1211,6 +1219,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
{
pos++;
*ml_comment= 0;
+ need_space= 1;
}
else
{ // Add found char to buffer
@@ -1220,7 +1229,14 @@ static bool add_line(String &buffer,char *line,char *in_string,
(inchar == '\'' || inchar == '"' || inchar == '`'))
*in_string= (char) inchar;
if (!*ml_comment)
+ {
+ if (need_space && !my_isspace(charset_info, (char)inchar))
+ {
+ *out++= ' ';
+ need_space= 0;
+ }
*out++= (char) inchar;
+ }
}
}
if (out != line || !buffer.is_empty())
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 24fe14b6675..32e0dfdb837 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -727,7 +727,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
new_line = 1;
- if (mysql_query(mysql, "show status") ||
+ if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
!(res = mysql_store_result(mysql)))
{
my_printf_error(0, "unable to show status; error: '%s'", MYF(ME_BELL),
@@ -1346,6 +1346,3 @@ static my_bool wait_pidfile(char *pidfile, time_t last_modified,
}
DBUG_RETURN(error);
}
-#ifdef __GNUC__
-FIX_GCC_LINKING_PROBLEM
-#endif
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 59c90f59e8e..1a628bd08c7 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1458,4 +1458,3 @@ int main(int argc, char** argv)
#include "log_event.cc"
#endif
-FIX_GCC_LINKING_PROBLEM
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b07a36aa7ad..976a6642ea0 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -83,7 +83,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
opt_delete_master_logs=0, tty_password=0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
- opt_hex_blob=0, opt_order_by_primary=0;
+ opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
@@ -257,6 +257,9 @@ static struct my_option my_long_options[] =
"use the directive multiple times, once for each table. Each table must "
"be specified with both database and table names, e.g. --ignore-table=database.table",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
+ (gptr*) &opt_ignore, (gptr*) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
(gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1100,13 +1103,15 @@ static uint get_table_structure(char *table, char *db)
my_bool init=0;
uint numFields;
char *strpos, *result_table, *opt_quoted_table;
- const char *delayed;
+ const char *insert_option;
char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3];
char table_buff2[NAME_LEN*2+3];
FILE *sql_file = md_result_file;
DBUG_ENTER("get_table_structure");
- delayed= opt_delayed ? " DELAYED " : "";
+ insert_option= (opt_delayed && opt_ignore) ? " DELAYED IGNORE " :
+ opt_delayed ? " DELAYED " :
+ opt_ignore ? " IGNORE " : "";
if (verbose)
fprintf(stderr, "-- Retrieving table structure for table %s...\n", table);
@@ -1190,11 +1195,11 @@ static uint get_table_structure(char *table, char *db)
if (cFlag)
my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s (",
- delayed, opt_quoted_table);
+ insert_option, opt_quoted_table);
else
{
my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ",
- delayed, opt_quoted_table);
+ insert_option, opt_quoted_table);
if (!extended_insert)
strcat(insert_pat,"(");
}
@@ -1258,11 +1263,11 @@ static uint get_table_structure(char *table, char *db)
}
if (cFlag)
my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s (",
- delayed, result_table);
+ insert_option, result_table);
else
{
my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ",
- delayed, result_table);
+ insert_option, result_table);
if (!extended_insert)
strcat(insert_pat,"(");
}
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 5631d296a54..85c8f123082 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -28,7 +28,7 @@
#include <sslopt-vars.h>
static my_string host=0,opt_password=0,user=0;
-static my_bool opt_show_keys= 0, opt_compress= 0, opt_status= 0,
+static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0,
tty_password= 0, opt_table_type= 0;
static uint opt_verbose=0;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
@@ -71,8 +71,7 @@ int main(int argc, char **argv)
char *pos= argv[argc-1], *to;
for (to= pos ; *pos ; pos++, to++)
{
- switch (*pos)
- {
+ switch (*pos) {
case '*':
*pos= '%';
first_argument_uses_wildcards= 1;
@@ -163,6 +162,10 @@ static struct my_option my_long_options[] =
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", (gptr*) &default_charset,
(gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"count", OPT_COUNT,
+ "Show number of rows per table (may be slow for not MyISAM tables)",
+ (gptr*) &opt_count, (gptr*) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
(gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -308,6 +311,14 @@ get_options(int *argc,char ***argv)
if (tty_password)
opt_password=get_tty_password(NullS);
+ if (opt_count)
+ {
+ /*
+ We need to set verbose to 2 as we need to change the output to include
+ the number-of-rows column
+ */
+ opt_verbose= 2;
+ }
return;
}
@@ -322,7 +333,7 @@ list_dbs(MYSQL *mysql,const char *wild)
char query[255];
MYSQL_FIELD *field;
MYSQL_RES *result;
- MYSQL_ROW row, trow, rrow;
+ MYSQL_ROW row, rrow;
if (!(result=mysql_list_dbs(mysql,wild)))
{
@@ -352,11 +363,6 @@ list_dbs(MYSQL *mysql,const char *wild)
if (opt_verbose)
{
- /*
- * Original code by MG16373; Slightly modified by Monty.
- * Print now the count of tables and rows for each database.
- */
-
if (!(mysql_select_db(mysql,row[0])))
{
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
@@ -366,6 +372,8 @@ list_dbs(MYSQL *mysql,const char *wild)
rowcount = 0;
if (opt_verbose > 1)
{
+ /* Print the count of tables and rows for each database */
+ MYSQL_ROW trow;
while ((trow = mysql_fetch_row(tresult)))
{
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
@@ -487,10 +495,6 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
while ((row = mysql_fetch_row(result)))
{
- /*
- * Modified by MG16373
- * Print now the count of rows for each table.
- */
counter++;
if (opt_verbose > 0)
{
@@ -510,6 +514,7 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
if (opt_verbose > 1)
{
+ /* Print the count of rows for each table */
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
if (!(mysql_query(mysql,query)))
{
@@ -574,7 +579,7 @@ list_table_status(MYSQL *mysql,const char *db,const char *wild)
MYSQL_RES *result;
MYSQL_ROW row;
- end=strxmov(query,"show table status from ",db,NullS);
+ end=strxmov(query,"show table status from `",db,"`",NullS);
if (wild && wild[0])
strxmov(end," like '",wild,"'",NullS);
if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
@@ -600,8 +605,8 @@ list_table_status(MYSQL *mysql,const char *db,const char *wild)
}
/*
-** list fields uses field interface as an example of how to parse
-** a MYSQL FIELD
+ list fields uses field interface as an example of how to parse
+ a MYSQL FIELD
*/
static int
@@ -612,6 +617,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
MYSQL_RES *result;
MYSQL_ROW row;
ulong rows;
+ LINT_INIT(rows);
if (mysql_select_db(mysql,db))
{
@@ -619,16 +625,20 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
mysql_error(mysql));
return 1;
}
- sprintf(query,"select count(*) from `%s`", table);
- if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
+
+ if (opt_count)
{
- fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
- my_progname,db,table,mysql_error(mysql));
- return 1;
+ sprintf(query,"select count(*) from `%s`", table);
+ if (mysql_query(mysql,query) || !(result=mysql_store_result(mysql)))
+ {
+ fprintf(stderr,"%s: Cannot get record count for db: %s, table: %s: %s\n",
+ my_progname,db,table,mysql_error(mysql));
+ return 1;
+ }
+ row= mysql_fetch_row(result);
+ rows= (ulong) strtoull(row[0], (char**) 0, 10);
+ mysql_free_result(result);
}
- row = mysql_fetch_row(result);
- rows = (ulong) strtoull(row[0], (char**) 0, 10);
- mysql_free_result(result);
end=strmov(strmov(strmov(query,"show /*!32332 FULL */ columns from `"),table),"`");
if (wild && wild[0])
@@ -640,8 +650,9 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
return 1;
}
- printf("Database: %s Table: %s Rows: %lu", db, table, rows);
-
+ printf("Database: %s Table: %s", db, table);
+ if (opt_count)
+ printf(" Rows: %lu", rows);
if (wild && wild[0])
printf(" Wildcard: %s",wild);
putchar('\n');
@@ -675,7 +686,7 @@ list_fields(MYSQL *mysql,const char *db,const char *table,
/*****************************************************************************
-** General functions to print a nice ascii-table from data
+ General functions to print a nice ascii-table from data
*****************************************************************************/
static void
diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am
index a3d73a7082a..03f3eb65fbc 100644
--- a/cmd-line-utils/libedit/Makefile.am
+++ b/cmd-line-utils/libedit/Makefile.am
@@ -22,9 +22,9 @@ libedit_a_DEPENDENCIES = @LIBEDIT_LOBJECTS@
pkginclude_HEADERS = readline/readline.h
-noinst_HEADERS = chared.h el.h histedit.h key.h parse.h refresh.h sig.h \
+noinst_HEADERS = chared.h el.h el_term.h histedit.h key.h parse.h refresh.h sig.h \
sys.h tokenizer.h config.h hist.h map.h prompt.h read.h \
- search.h tty.h libedit_term.h
+ search.h tty.h libedit_term.h vis.h
EXTRA_DIST = makelist.sh np/unvis.c np/strlcpy.c np/vis.c np/vis.h np/strlcat.c np/fgetln.c
diff --git a/cmd-line-utils/libedit/config.h b/cmd-line-utils/libedit/config.h
index b6f002d5b9e..642123d1ddc 100644
--- a/cmd-line-utils/libedit/config.h
+++ b/cmd-line-utils/libedit/config.h
@@ -2,8 +2,10 @@
#include "my_config.h"
#include "sys.h"
+#if defined(LIBC_SCCS) && !defined(lint)
#define __RCSID(x)
#define __COPYRIGHT(x)
+#endif
#define __RENAME(x)
#define _DIAGASSERT(x)
diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c
index a506fa6de09..b2bcf5f146c 100644
--- a/cmd-line-utils/readline/terminal.c
+++ b/cmd-line-utils/readline/terminal.c
@@ -346,7 +346,7 @@ get_term_capabilities (bp)
register unsigned int i;
for (i = 0; i < NUM_TC_STRINGS; i++)
-# ifdef __LCC__
+# if defined(__LCC__) || defined(__MWERKS__)
*(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
# else
*(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp);
diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4
index 201702e5379..8c961ef84e0 100644
--- a/config/ac-macros/misc.m4
+++ b/config/ac-macros/misc.m4
@@ -646,8 +646,8 @@ m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
'void exit (int);' \
'#include <stdlib.h>'
do
- _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
-$ac_declaration],
+ _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration
+@%:@include <stdlib.h>],
[exit (42);])],
[],
[continue])
@@ -693,3 +693,20 @@ dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_BIG_TABLES SECTION
dnl ---------------------------------------------------------------------------
+dnl MYSQL_NEEDS_MYSYS_NEW
+AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW],
+[AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new,
+[
+AC_LANG_PUSH(C++)
+AC_TRY_LINK([], [
+class A { public: int b; }; A *a=new A; a->b=10; delete a;
+], mysql_use_mysys_new=no, mysql_use_mysys_new=yes)
+AC_LANG_POP(C++)
+])
+if test "$mysql_use_mysys_new" = "yes"
+then
+ AC_DEFINE([USE_MYSYS_NEW], [1], [Needs to use mysys_new helpers])
+fi
+])
+
+
diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4
new file mode 100644
index 00000000000..ada1a2c0bd1
--- /dev/null
+++ b/config/ac-macros/yassl.m4
@@ -0,0 +1,33 @@
+AC_CONFIG_FILES(extra/yassl/Makefile dnl
+extra/yassl/taocrypt/Makefile dnl
+extra/yassl/taocrypt/src/Makefile dnl
+extra/yassl/src/Makefile)
+
+AC_DEFUN([MYSQL_CHECK_YASSL], [
+ AC_MSG_CHECKING(for yaSSL)
+ AC_ARG_WITH([yassl],
+ [ --with-yassl Include the yaSSL support],
+ [yassl=yes],
+ [yassl=no])
+
+ if test "$yassl" = "yes"
+ then
+ if test "$openssl" != "no"
+ then
+ AC_MSG_ERROR([Cannot configure MySQL to use yaSSL and OpenSSL simultaneously.])
+ fi
+ AC_MSG_RESULT([using bundled yaSSL])
+ yassl_dir="extra/yassl"
+ openssl_libs="\
+ \$(top_builddir)/extra/yassl/src/libyassl.a\
+ \$(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.a"
+ openssl_includes="-I\$(top_srcdir)/extra/yassl/include"
+ AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.])
+ else
+ yassl_dir=""
+ AC_MSG_RESULT(no)
+ fi
+ AC_SUBST(openssl_libs)
+ AC_SUBST(openssl_includes)
+ AC_SUBST(yassl_dir)
+])
diff --git a/configure.in b/configure.in
index da707080006..44fe34ad655 100644
--- a/configure.in
+++ b/configure.in
@@ -47,6 +47,7 @@ sinclude(config/ac-macros/large_file.m4)
sinclude(config/ac-macros/misc.m4)
sinclude(config/ac-macros/openssl.m4)
sinclude(config/ac-macros/readline.m4)
+sinclude(config/ac-macros/yassl.m4)
sinclude(config/ac-macros/zlib.m4)
# Remember to add a directory sql/share/LANGUAGE
@@ -122,8 +123,25 @@ AM_SANITY_CHECK
# This is needed is SUBDIRS is set
AC_PROG_MAKE_SET
-# This is need before AC_PROG_CC
-#
+##############################################################################
+# The below section needs to be done before AC_PROG_CC
+##############################################################################
+
+# Hack for OS X/Darwin and Metrowerks CodeWarrior
+AC_ARG_WITH(darwin-mwcc,
+[ --with-darwin-mwcc Use Metrowerks CodeWarrior wrappers on OS X/Darwin],[
+ builddir=`pwd`
+ ccwrapper="$builddir/support-files/MacOSX/mwcc-wrapper"
+ arwrapper="$builddir/support-files/MacOSX/mwar-wrapper"
+ CC="$ccwrapper"
+ CXX="$ccwrapper"
+ LD="$ccwrapper"
+ AR="$arwrapper"
+ RANLIB=:
+ export CC CXX LD AR RANLIB
+ AC_SUBST(AR)
+ AC_SUBST(RANLIB)
+])
if test "x${CFLAGS-}" = x ; then
cflags_is_set=no
@@ -143,6 +161,8 @@ else
ldflags_is_set=yes
fi
+################ End of section to be done before AC_PROG_CC #################
+
# The following hack should ensure that configure doesn't add optimizing
# or debugging flags to CFLAGS or CXXFLAGS
# C_EXTRA_FLAGS are flags that are automaticly added to both
@@ -293,7 +313,7 @@ case "$target_os" in
AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
case "$LDFLAGS" in
*-belf*) ;;
- *) echo "Adding -belf option to ldflags."
+ *) AC_MSG_WARN([Adding -belf option to ldflags.])
LDFLAGS="$LDFLAGS -belf"
;;
esac
@@ -304,7 +324,7 @@ case "$target_os" in
case "$LDFLAGS" in
*-belf*) ;;
*)
- echo "Adding -belf option to ldflags."
+ AC_MSG_WARN([Adding -belf option to ldflags.])
LDFLAGS="$LDFLAGS -belf"
;;
esac
@@ -335,30 +355,10 @@ AC_SUBST(LD)
AC_SUBST(INSTALL_SCRIPT)
export CC CXX CFLAGS LD LDFLAGS AR
-echo "GXX: $GXX"
-if test "$GXX" = "yes"
-then
- # mysqld requires -fno-implicit-templates.
- # Disable exceptions as they seams to create problems with gcc and threads.
- # mysqld doesn't use run-time-type-checking, so we disable it.
- CXXFLAGS="$CXXFLAGS -fno-implicit-templates -fno-exceptions -fno-rtti"
-
- #CXX_VERNO=`echo $CXX_VERSION | sed -e 's/[[^0-9. ]]//g; s/^ *//g; s/ .*//g'`
- echo "CXX: $CXX"
- if echo $CXX | grep gcc > /dev/null 2>&1
- then
- echo "Setting CXXFLAGS"
- # If you are using 'gcc' 3.0 (not g++) to compile C++ programs on Linux,
- # we will gets some problems when linking static programs.
- # The following code is used to fix this problem.
- CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL"
- echo "Using MYSYS_NEW for static linking with gcc"
- fi
-fi
# Avoid bug in fcntl on some versions of linux
AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os")
-# Any wariation of Linux
+# Any variation of Linux
if expr "$target_os" : "[[Ll]]inux.*" > /dev/null
then
MYSQLD_DEFAULT_SWITCHES="--skip-locking"
@@ -936,7 +936,7 @@ case $SYSTEM_TYPE in
*solaris2.7*)
# Solaris 2.7 has a broken /usr/include/widec.h
# Make a fixed copy in ./include
- echo "Fixing broken include files for $SYSTEM_TYPE"
+ AC_MSG_WARN([Fixing broken include files for $SYSTEM_TYPE])
echo " - Creating local copy of widec.h"
if test ! -d include
then
@@ -950,7 +950,7 @@ case $SYSTEM_TYPE in
*solaris2.8*)
# Solaris 2.8 has a broken /usr/include/widec.h
# Make a fixed copy in ./include
- echo "Fixing broken include files for $SYSTEM_TYPE"
+ AC_MSG_WARN([Fixing broken include files for $SYSTEM_TYPE])
echo " - Creating local copy of widec.h"
if test ! -d include
then
@@ -962,7 +962,7 @@ case $SYSTEM_TYPE in
CXXFLAGS="$CXXFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
;;
*solaris2.5.1*)
- echo "Enabling getpass() workaround for Solaris 2.5.1"
+ AC_MSG_WARN([Enabling getpass() workaround for Solaris 2.5.1])
CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS -DHAVE_RWLOCK_T";
CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T -DSOLARIS"
;;
@@ -971,26 +971,26 @@ case $SYSTEM_TYPE in
CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T"
;;
*SunOS*)
- echo "Enabling getpass() workaround for SunOS"
+ AC_MSG_WARN([Enabling getpass() workaround for SunOS])
CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS";
;;
*hpux10.20*)
- echo "Enabling workarounds for hpux 10.20"
+ AC_MSG_WARN([Enabling workarounds for hpux 10.20])
CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
if test "$with_named_thread" = "no"
then
- echo "Using --with-named-thread=-lpthread"
+ AC_MSG_WARN([Using --with-named-thread=-lpthread])
with_named_thread="-lcma"
fi
;;
*hpux11.*)
- echo "Enabling workarounds for hpux 11"
+ AC_MSG_WARN([Enabling workarounds for hpux 11])
CFLAGS="$CFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
CXXFLAGS="$CXXFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
if test "$with_named_thread" = "no"
then
- echo "Using --with-named-thread=-lpthread"
+ AC_MSG_WARN([Using --with-named-thread=-lpthread])
with_named_thread="-lpthread"
fi
# Fixes for HPUX 11.0 compiler
@@ -1046,7 +1046,7 @@ case $SYSTEM_TYPE in
fi
;;
*freebsd*)
- echo "Adding fix for interrupted reads"
+ AC_MSG_WARN([Adding fix for interrupted reads])
OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
if test "$OSVERSION" -gt "480100" && \
test "$OSVERSION" -lt "500000" || \
@@ -1059,13 +1059,13 @@ case $SYSTEM_TYPE in
fi
;;
*netbsd*)
- echo "Adding flag -Dunix"
+ AC_MSG_WARN([Adding flag -Dunix])
CFLAGS="$CFLAGS -Dunix"
CXXFLAGS="$CXXFLAGS -Dunix"
OVERRIDE_MT_LD_ADD="\$(top_srcdir)/mit-pthreads/obj/libpthread.a"
;;
*bsdi*)
- echo "Adding fix for BSDI"
+ AC_MSG_WARN([Adding fix for BSDI])
CFLAGS="$CFLAGS -D__BSD__ -DHAVE_BROKEN_REALPATH"
AC_DEFINE_UNQUOTED([SOCKOPT_OPTLEN_TYPE], [size_t],
[Last argument to get/setsockopt])
@@ -1073,13 +1073,13 @@ case $SYSTEM_TYPE in
*sgi-irix6*)
if test "$with_named_thread" = "no"
then
- echo "Using --with-named-thread=-lpthread"
+ AC_MSG_WARN([Using --with-named-thread=-lpthread])
with_named_thread="-lpthread"
fi
CXXFLAGS="$CXXFLAGS -D_BOOL"
;;
*aix4.3*)
- echo "Adding defines for AIX"
+ AC_MSG_WARN([Adding defines for AIX])
CFLAGS="$CFLAGS -Wa,-many -DUNDEF_HAVE_INITGROUPS -DSIGNALS_DONT_BREAK_READ"
CXXFLAGS="$CXXFLAGS -Wa,-many -DUNDEF_HAVE_INITGROUPS -DSIGNALS_DONT_BREAK_READ"
;;
@@ -1087,11 +1087,11 @@ dnl Is this the right match for DEC OSF on alpha?
*dec-osf*)
if test "$ac_cv_prog_gcc" = "yes" && test "$host_cpu" = "alpha"
then
- echo "Adding defines for DEC OSF on alpha"
+ AC_MSG_WARN([Adding defines for DEC OSF on alpha])
CFLAGS="$CFLAGS -mieee"
CXXFLAGS="$CXXFLAGS -mieee"
fi
- echo "Adding defines for OSF1"
+ AC_MSG_WARN([Adding defines for OSF1])
# gethostbyname_r is deprecated and doesn't work ok on OSF1
CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
@@ -1378,7 +1378,7 @@ then
CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
fi
else
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
+ { AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) };
fi
else
AC_MSG_RESULT("no")
@@ -1424,7 +1424,7 @@ then
fi
AC_MSG_RESULT("yes")
else
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
+ { AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) };
fi
else
AC_MSG_RESULT("no")
@@ -1467,7 +1467,7 @@ then
fi
AC_MSG_RESULT("yes")
else
- { echo "configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
+ { AC_MSG_ERROR([configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual.]) };
fi
else
AC_MSG_RESULT("no")
@@ -1723,6 +1723,7 @@ AC_TYPE_OFF_T
AC_STRUCT_ST_RDEV
AC_HEADER_TIME
AC_STRUCT_TM
+MYSQL_NEEDS_MYSYS_NEW
# AC_CHECK_SIZEOF return 0 when it does not find the size of a
# type. We want a error instead.
AC_CHECK_SIZEOF(char, 1)
@@ -1798,6 +1799,9 @@ If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try
again]);
fi
fi
+AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include <sys/types.h>])
+AC_CHECK_TYPES([size_t], [], [], [#include <stdio.h>])
+
MYSQL_PTHREAD_YIELD
######################################################################
@@ -2238,7 +2242,7 @@ if test "$with_tools" = "yes"
then
if test "$THREAD_SAFE_CLIENT" = "no"
then
- echo "Warning: extra-tools disabled because --enable-thread-safe-client wasn't used"
+ AC_MSG_WARN([extra-tools disabled because --enable-thread-safe-client wasn't used])
else
tools_dirs="tools"
fi
@@ -2259,6 +2263,7 @@ AC_SUBST(tools_dirs)
#MYSQL_CHECK_CPU
MYSQL_CHECK_VIO
MYSQL_CHECK_OPENSSL
+MYSQL_CHECK_YASSL
libmysqld_dirs=
if test "$with_embedded_server" = "yes"
diff --git a/extra/Makefile.am b/extra/Makefile.am
index dac6bf0fc0b..3aa4c531709 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -24,6 +24,7 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \
$(top_builddir)/include/mysqld_ername.h
pkginclude_HEADERS= $(BUILT_SOURCES)
CLEANFILES = $(BUILT_SOURCES)
+DIST_SUBDIRS= yassl
# This will build mysqld_error.h and sql_state.h
$(top_builddir)/include/mysqld_error.h: comp_err
diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c
index d5836cb0dc8..946ac219e1a 100644
--- a/extra/my_print_defaults.c
+++ b/extra/my_print_defaults.c
@@ -27,12 +27,20 @@
const char *config_file="my"; /* Default config file */
uint verbose= 0, opt_defaults_file_used= 0;
+const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace";
static struct my_option my_long_options[] =
{
{"config-file", 'c', "The config file to be used.",
(gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+#ifdef DBUG_OFF
+ {"debug", '#', "This is a non-debug version. Catch this and exit",
+ 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#else
+ {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
+ (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"defaults-file", 'c', "Synonym for --config-file.",
(gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
@@ -68,6 +76,7 @@ static void usage(my_bool version)
puts("Prints all arguments that is give to some program using the default files");
printf("Usage: %s [OPTIONS] groups\n", my_progname);
my_print_help(my_long_options);
+ my_print_default_files(config_file);
my_print_variables(my_long_options);
printf("\nExample usage:\n%s --config-file=my client mysql\n", my_progname);
}
@@ -95,6 +104,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'V':
usage(1);
exit(0);
+ case '#':
+ DBUG_PUSH(argument ? argument : default_dbug_option);
+ break;
}
return 0;
}
@@ -118,7 +130,7 @@ static int get_options(int *argc,char ***argv)
int main(int argc, char **argv)
{
int count, error;
- char **load_default_groups, *tmp_arguments[2],
+ char **load_default_groups, *tmp_arguments[3],
**argument, **arguments;
char *defaults, *extra_defaults;
MY_INIT(argv[0]);
diff --git a/extra/yassl/AUTHORS b/extra/yassl/AUTHORS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/AUTHORS
diff --git a/extra/yassl/ChangeLog b/extra/yassl/ChangeLog
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/ChangeLog
diff --git a/extra/yassl/INSTALL b/extra/yassl/INSTALL
new file mode 100644
index 00000000000..54caf7c190f
--- /dev/null
+++ b/extra/yassl/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am
new file mode 100644
index 00000000000..7c1f2ea5acb
--- /dev/null
+++ b/extra/yassl/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = taocrypt src
+EXTRA_DIST = yassl.dsp yassl.dsw mySTL/*.hpp
diff --git a/extra/yassl/NEWS b/extra/yassl/NEWS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/NEWS
diff --git a/extra/yassl/README b/extra/yassl/README
new file mode 100644
index 00000000000..198a1031cb7
--- /dev/null
+++ b/extra/yassl/README
@@ -0,0 +1,263 @@
+yaSSL Release notes, version 0.9.6
+
+This release of yaSSL contains minor bug fixes, removal of STL support, and
+removal of exceptions and rtti so that the library can be linked without the
+std c++ library.
+
+--To build on Linux, Solaris, FreeBSD, Mac OS X, or Cygwin
+
+./configure
+make
+
+run testsuite from yaSSL-Home/testsuite to test the build
+
+
+--To build on Win32
+
+Choose (Re)Build All from the project workspace
+
+run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build
+
+
+
+******************yaSSL Release notes, version 0.9.2
+
+This release of yaSSL contains minor bug fixes, expanded certificate
+verification and chaining, and improved documentation.
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.9.0
+
+This release of yaSSL contains minor bug fixes, client verification handling,
+hex and base64 encoing/decoding, and an improved test suite.
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.8.0
+
+This release of yaSSL contains minor bug fixes, and initial porting effort to
+64bit, BigEndian, and more UNIX systems.
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.6.0
+
+This release of yaSSL contains minor bug fixes, source cleanup, and binary beta
+(1) of the yaSSL libraries.
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.5.0
+
+This release of yaSSL contains minor bug fixes, full session resumption
+support, and initial testing suite support.
+
+
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.4.0
+
+This release of yaSSL contains minor bug fixes, an optional memory tracker,
+an echo client and server with input/output redirection for load testing,
+and initial session caching support.
+
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.3.5
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library including a full test suite.
+
+
+*******************yaSSL Release notes, version 0.3.0
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library including AES and an improved random number generator. GNU autoconf
+and automake are now used to simplify the build process on Linux.
+
+*** Linux Build process
+
+./configure
+make
+
+*** Windows Build process
+
+open the yassl workspace and build the project
+
+
+*******************yaSSL Release notes, version 0.2.9
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library.
+
+See the notes at the bottom of this page for build instructions.
+
+
+*******************yaSSL Release notes, version 0.2.5
+
+This release of yaSSL contains minor bug fixes and a beta binary of the yaSSL
+libraries for win32 and linux.
+
+See the notes at the bottom of this page for build instructions.
+
+
+
+*******************yaSSL Release notes, version 0.2.0
+
+This release of yaSSL contains minor bug fixes and initial alternate crypto
+functionality.
+
+*** Complete Build ***
+
+See the notes in Readme.txt for build instructions.
+
+*** Update Build ***
+
+If you have already done a complete build of yaSSL as described in the release
+0.0.1 - 0.1.0 notes and downloaded the update to 0.2.0, place the update file
+yassl-update-0.2.0.tar.gz in the yaSSL home directory and issue the command:
+
+gzip -cd yassl-update-0.2.0.tar.gz | tar xvf -
+
+to update the previous release.
+
+Then issue the make command on linux or rebuild the yaSSL project on Windows.
+
+*******************yaSSL Release notes, version 0.1.0
+
+This release of yaSSL contains minor bug fixes, full client and server TLSv1
+support including full ephemeral Diffie-Hellman support, SSL type RSA and DSS
+signing and verification, and initial stunnel 4.05 build support.
+
+
+
+*********************yaSSL Release notes, version 0.0.3
+
+The third release of yaSSL contains minor bug fixes, client certificate
+enhancements, and initial ephemeral Diffie-Hellman integration:
+
+
+
+*********************
+
+yaSSL Release notes, version 0.0.2
+
+The second release of yaSSL contains minor bug fixes, client certificate
+enhancements, session resumption, and improved TLS support including:
+
+- HMAC for MD5 and SHA-1
+- PRF (pseudo random function)
+- Master Secret and Key derivation routines
+- Record Authentication codes
+- Finish verify data check
+
+Once ephemeral RSA and DH are added yaSSL will be fully complaint with TLS.
+
+
+
+**********************
+
+yassl Release notes, version 0.0.1
+
+The first release of yassl supports normal RSA mode SSLv3 connections with
+support for SHA-1 and MD5 digests. Ciphers include DES, 3DES, and RC4.
+
+yassl uses the CryptoPP library for cryptography, the source is available at
+www.cryptopp.com .
+
+yassl uses CML (the Certificate Management Library) for x509 support. More
+features will be in future versions. The CML source is available for download
+from www.digitalnet.com/knowledge/cml_home.htm .
+
+The next release of yassl will support the 3 lesser-used SSL connection modes;
+HandShake resumption, Ephemeral RSA (or DH), and Client Authentication as well
+as full support for TLS. Backwards support for SSLv2 is not planned at this
+time.
+
+
+**********************
+
+Building yassl on linux:
+
+use the ./buildall script to build everything.
+
+buildall will configure and build CML, CryptoPP, and yassl. Testing was
+preformed with gcc version 3.3.2 on kernel 2.4.22.
+
+
+**********************
+
+Building yassl on Windows:
+
+Testing was preformed on Windows 2000 with Visual C++ 6 sp5.
+
+1) decompress esnacc_r16.tgz in place, see buildall for syntax if unsure
+
+2) decompress smp_r23.tgz in place
+
+3) unzip cryptopp51/crypto51.zip in place
+
+4) Build SNACC (part of CML) using snacc_builds.dsw in the SNACC directory
+
+5) Build SMP (part of CMP) using smp.dsw in the smp directory
+
+6) Build yassl using yassl.dsw
+
+
+**********************
+
+examples, server and client:
+
+Please see the server and client examples in both versions to see how to link
+to yassl and the support libraries. On linux do 'make server' and 'make
+client' to build them. On Windows you will find the example projects in the
+main workspace, yassl.dsw.
+
+The example server and client are compatible with openssl.
+
+
+**********************
+
+Building yassl into mysql on linux:
+
+Testing was done using mysql version 4.0.17.
+
+alter openssl_libs in the configure file, line 21056. Change '-lssl -lcrypto'
+to '-lyassl -lcryptopp -lcmapi -lcmlasn -lctil -lc++asn1'.
+
+see build/config_command for the configure command used to configure mysql
+please change /home/touska/ to the relevant directory of course.
+
+add yassl/lib to the LD_LIBRARY_PATH because libmysql/conf_to_src does not
+use the ssl lib directory though it does use the ssl libraries.
+
+make
+
+make install
+
+
+*********************
+
+License: yassl is currently under the GPL, please see license information
+in the source and include files.
+
+
+*********************
+
+Contact: please send comments or questions to Todd A Ouska at todd@yassl.com
+and/or Larry Stefonic at larry@yassl.com or 425-741-6858.
+
+
+
diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp
new file mode 100644
index 00000000000..126bdbc19b7
--- /dev/null
+++ b/extra/yassl/include/buffer.hpp
@@ -0,0 +1,207 @@
+/* buffer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL buffer header defines input and output buffers to simulate streaming
+ * with SSL types and sockets
+ */
+
+#ifndef yaSSL_BUFFER_HPP
+#define yaSSL_BUFFER_HPP
+
+#include <cassert> // assert
+#include "yassl_error.hpp" // Error
+#include "memory.hpp" // mySTL::auto_ptr
+#include "algorithm.hpp" // mySTL::swap
+
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+
+namespace yaSSL {
+
+typedef unsigned char byte;
+typedef unsigned int uint;
+const uint AUTO = 0xFEEDBEEF;
+
+
+// Checking Policy should implement a check function that tests whether the
+// index is within the size limit of the array
+struct Check {
+ void check(uint i, uint limit);
+};
+
+
+struct NoCheck {
+ void check(uint, uint);
+};
+
+/* input_buffer operates like a smart c style array with a checking option,
+ * meant to be read from through [] with AUTO index or read().
+ * Should only write to at/near construction with assign() or raw (e.g., recv)
+ * followed by add_size with the number of elements added by raw write.
+ *
+ * Not using vector because need checked []access, offset, and the ability to
+ * write to the buffer bulk wise and have the correct size
+ */
+
+class input_buffer : public Check {
+ uint size_; // number of elements in buffer
+ uint current_; // current offset position in buffer
+ byte* buffer_; // storage for buffer
+ byte* end_; // end of storage marker
+public:
+ input_buffer();
+
+ explicit input_buffer(uint s);
+
+ // with assign
+ input_buffer(uint s, const byte* t, uint len);
+
+ ~input_buffer();
+
+ // users can pass defualt zero length buffer and then allocate
+ void allocate(uint s);
+
+ // for passing to raw writing functions at beginning, then use add_size
+ byte* get_buffer() const;
+
+ // after a raw write user can set new size
+ // if you know the size before the write use assign()
+ void add_size(uint i);
+
+ uint get_capacity() const;
+
+ uint get_current() const;
+
+ uint get_size() const;
+
+ uint get_remaining() const;
+
+ void set_current(uint i);
+
+ // read only access through [], advance current
+ // user passes in AUTO index for ease of use
+ const byte& operator[](uint i);
+
+ // end of input test
+ bool eof();
+
+ // peek ahead
+ byte peek() const;
+
+ // write function, should use at/near construction
+ void assign(const byte* t, uint s);
+
+ // use read to query input, adjusts current
+ void read(byte* dst, uint length);
+
+private:
+ input_buffer(const input_buffer&); // hide copy
+ input_buffer& operator=(const input_buffer&); // and assign
+};
+
+
+/* output_buffer operates like a smart c style array with a checking option.
+ * Meant to be written to through [] with AUTO index or write().
+ * Size (current) counter increases when written to. Can be constructed with
+ * zero length buffer but be sure to allocate before first use.
+ * Don't use add write for a couple bytes, use [] instead, way less overhead.
+ *
+ * Not using vector because need checked []access and the ability to
+ * write to the buffer bulk wise and retain correct size
+ */
+class output_buffer : public Check {
+ uint current_; // current offset and elements in buffer
+ byte* buffer_; // storage for buffer
+ byte* end_; // end of storage marker
+public:
+ // default
+ output_buffer();
+
+ // with allocate
+ explicit output_buffer(uint s);
+
+ // with assign
+ output_buffer(uint s, const byte* t, uint len);
+
+ ~output_buffer();
+
+ uint get_size() const;
+
+ uint get_capacity() const;
+
+ void set_current(uint c);
+
+ // users can pass defualt zero length buffer and then allocate
+ void allocate(uint s);
+
+ // for passing to reading functions when finished
+ const byte* get_buffer() const;
+
+ // allow write access through [], update current
+ // user passes in AUTO as index for ease of use
+ byte& operator[](uint i);
+
+ // end of output test
+ bool eof();
+
+ void write(const byte* t, uint s);
+
+private:
+ output_buffer(const output_buffer&); // hide copy
+ output_buffer& operator=(const output_buffer&); // and assign
+};
+
+
+
+
+// turn delete an incomplete type into comipler error instead of warning
+template <typename T>
+inline void checked_delete(T* p)
+{
+ typedef char complete_type[sizeof(T) ? 1 : -1];
+ (void)sizeof(complete_type);
+ delete p;
+}
+
+
+// checked delete functor increases effeciency, no indirection on function call
+// sets pointer to zero so safe for std conatiners
+struct del_ptr_zero
+{
+ template <typename T>
+ void operator()(T*& p) const
+ {
+ T* tmp = 0;
+ mySTL::swap(tmp, p);
+ checked_delete(tmp);
+ }
+};
+
+
+
+} // naemspace
+
+#endif // yaSSL_BUUFER_HPP
diff --git a/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp
new file mode 100644
index 00000000000..2381347c27e
--- /dev/null
+++ b/extra/yassl/include/cert_wrapper.hpp
@@ -0,0 +1,124 @@
+/* cert_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The certificate wrapper header defines certificate management functions
+ *
+ */
+
+
+#ifndef yaSSL_CERT_WRAPPER_HPP
+#define yaSSL_CERT_WRAPPER_HPP
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+
+#include "yassl_types.hpp" // SignatureAlgorithm
+#include "buffer.hpp" // input_buffer
+#include "asn.hpp" // SignerList
+#include "list.hpp" // mySTL::list
+#include "algorithm.hpp" // mySTL::for_each
+
+namespace yaSSL {
+
+typedef unsigned char opaque;
+class X509; // forward openSSL type
+
+using TaoCrypt::SignerList;
+
+// an x509 version 3 certificate
+class x509 {
+ uint length_;
+ opaque* buffer_;
+public:
+ explicit x509(uint sz);
+ ~x509();
+
+ uint get_length() const;
+ const opaque* get_buffer() const;
+ opaque* use_buffer();
+
+ x509(const x509&);
+ x509& operator=(const x509&);
+private:
+ void Swap(x509&);
+};
+
+
+// Certificate Manager keeps a list of the cert chain and public key
+class CertManager {
+ typedef mySTL::list<x509*> CertList;
+
+ CertList list_; // self
+ input_buffer privateKey_;
+
+ CertList peerList_; // peer
+ input_buffer peerPublicKey_;
+ X509* peerX509_; // peer's openSSL X509
+
+ SignatureAlgorithm keyType_; // self key type
+ SignatureAlgorithm peerKeyType_; // peer's key type
+
+ SignerList signers_; // decoded CA keys and names
+ // plus verified chained certs
+ bool verifyPeer_;
+ bool failNoCert_;
+ bool sendVerify_;
+public:
+ CertManager();
+ ~CertManager();
+
+ void AddPeerCert(x509* x); // take ownership
+ void CopySelfCert(const x509* x);
+ int CopyCaCert(const x509* x);
+ int Validate();
+
+ int SetPrivateKey(const x509&);
+
+ const x509* get_cert() const;
+ const opaque* get_peerKey() const;
+ const opaque* get_privateKey() const;
+ X509* get_peerX509() const;
+ SignatureAlgorithm get_keyType() const;
+ SignatureAlgorithm get_peerKeyType() const;
+
+ uint get_peerKeyLength() const;
+ uint get_privateKeyLength() const;
+
+ bool verifyPeer() const;
+ bool failNoCert() const;
+ bool sendVerify() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+ void setSendVerify();
+private:
+ CertManager(const CertManager&); // hide copy
+ CertManager& operator=(const CertManager&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_CERT_WRAPPER_HPP
diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp
new file mode 100644
index 00000000000..fa60c774cd9
--- /dev/null
+++ b/extra/yassl/include/crypto_wrapper.hpp
@@ -0,0 +1,418 @@
+/* crypto_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The crypto wrapper header is used to define policies for the cipher
+ * components used by SSL. There are 3 policies to consider:
+ *
+ * 1) MAC, the Message Authentication Code used for each Message
+ * 2) Bulk Cipher, the Cipher used to encrypt/decrypt each Message
+ * 3) Atuhentication, the Digitial Signing/Verifiaction scheme used
+ *
+ * This header doesn't rely on a specific crypto libraries internals,
+ * only the implementation should.
+ */
+
+
+#ifndef yaSSL_CRYPTO_WRAPPER_HPP
+#define yaSSL_CRYPTO_WRAPPER_HPP
+
+#include "yassl_types.hpp"
+
+
+namespace yaSSL {
+
+
+// Digest policy should implement a get_digest, update, and get sizes for pad and
+// digest
+struct Digest {
+ virtual void get_digest(byte*) = 0;
+ virtual void get_digest(byte*, const byte*, unsigned int) = 0;
+ virtual void update(const byte*, unsigned int) = 0;
+ virtual uint get_digestSize() const = 0;
+ virtual uint get_padSize() const = 0;
+ virtual ~Digest() {}
+};
+
+
+// For use with NULL Digests
+struct NO_MAC : public Digest {
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+};
+
+
+// MD5 Digest
+class MD5 : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ MD5();
+ ~MD5();
+ MD5(const MD5&);
+ MD5& operator=(const MD5&);
+private:
+ struct MD5Impl;
+ MD5Impl* pimpl_;
+};
+
+
+// SHA-1 Digest
+class SHA : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ SHA();
+ ~SHA();
+ SHA(const SHA&);
+ SHA& operator=(const SHA&);
+private:
+ struct SHAImpl;
+ SHAImpl* pimpl_;
+
+};
+
+
+// RIPEMD-160 Digest
+class RMD : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ RMD();
+ ~RMD();
+ RMD(const RMD&);
+ RMD& operator=(const RMD&);
+private:
+ struct RMDImpl;
+ RMDImpl* pimpl_;
+
+};
+
+
+// HMAC_MD5
+class HMAC_MD5 : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_MD5(const byte*, unsigned int);
+ ~HMAC_MD5();
+private:
+ struct HMAC_MD5Impl;
+ HMAC_MD5Impl* pimpl_;
+
+ HMAC_MD5(const HMAC_MD5&);
+ HMAC_MD5& operator=(const HMAC_MD5&);
+};
+
+
+// HMAC_SHA-1
+class HMAC_SHA : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_SHA(const byte*, unsigned int);
+ ~HMAC_SHA();
+private:
+ struct HMAC_SHAImpl;
+ HMAC_SHAImpl* pimpl_;
+
+ HMAC_SHA(const HMAC_SHA&);
+ HMAC_SHA& operator=(const HMAC_SHA&);
+};
+
+
+// HMAC_RMD
+class HMAC_RMD : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_RMD(const byte*, unsigned int);
+ ~HMAC_RMD();
+private:
+ struct HMAC_RMDImpl;
+ HMAC_RMDImpl* pimpl_;
+
+ HMAC_RMD(const HMAC_RMD&);
+ HMAC_RMD& operator=(const HMAC_RMD&);
+};
+
+
+// BulkCipher policy should implement encrypt, decrypt, get block size,
+// and set keys for encrypt and decrypt
+struct BulkCipher {
+ virtual void encrypt(byte*, const byte*, unsigned int) = 0;
+ virtual void decrypt(byte*, const byte*, unsigned int) = 0;
+ virtual void set_encryptKey(const byte*, const byte* = 0) = 0;
+ virtual void set_decryptKey(const byte*, const byte* = 0) = 0;
+ virtual uint get_blockSize() const = 0;
+ virtual int get_keySize() const = 0;
+ virtual int get_ivSize() const = 0;
+ virtual ~BulkCipher() {}
+};
+
+
+// For use with NULL Ciphers
+struct NO_Cipher : public BulkCipher {
+ void encrypt(byte*, const byte*, unsigned int) {}
+ void decrypt(byte*, const byte*, unsigned int) {}
+ void set_encryptKey(const byte*, const byte*) {}
+ void set_decryptKey(const byte*, const byte*) {}
+ uint get_blockSize() const { return 0; }
+ int get_keySize() const { return 0; }
+ int get_ivSize() const { return 0; }
+};
+
+
+// SSLv3 and TLSv1 always use DES in CBC mode so IV is required
+class DES : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return DES_BLOCK; }
+ int get_keySize() const { return DES_KEY_SZ; }
+ int get_ivSize() const { return DES_IV_SZ; }
+ DES();
+ ~DES();
+private:
+ struct DESImpl;
+ DESImpl* pimpl_;
+
+ DES(const DES&); // hide copy
+ DES& operator=(const DES&); // & assign
+};
+
+
+// 3DES Encrypt-Decrypt-Encrypt in CBC mode
+class DES_EDE : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return DES_BLOCK; }
+ int get_keySize() const { return DES_EDE_KEY_SZ; }
+ int get_ivSize() const { return DES_IV_SZ; }
+ DES_EDE();
+ ~DES_EDE();
+private:
+ struct DES_EDEImpl;
+ DES_EDEImpl* pimpl_;
+
+ DES_EDE(const DES_EDE&); // hide copy
+ DES_EDE& operator=(const DES_EDE&); // & assign
+};
+
+
+// Alledged RC4
+class RC4 : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return 0; }
+ int get_keySize() const { return RC4_KEY_SZ; }
+ int get_ivSize() const { return 0; }
+ RC4();
+ ~RC4();
+private:
+ struct RC4Impl;
+ RC4Impl* pimpl_;
+
+ RC4(const RC4&); // hide copy
+ RC4& operator=(const RC4&); // & assign
+};
+
+
+// AES
+class AES : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return AES_BLOCK_SZ; }
+ int get_keySize() const;
+ int get_ivSize() const { return AES_IV_SZ; }
+ explicit AES(unsigned int = AES_128_KEY_SZ);
+ ~AES();
+private:
+ struct AESImpl;
+ AESImpl* pimpl_;
+
+ AES(const AES&); // hide copy
+ AES& operator=(const AES&); // & assign
+};
+
+
+// Random number generator
+class RandomPool {
+public:
+ void Fill(opaque* dst, uint sz) const;
+ RandomPool();
+ ~RandomPool();
+
+ int GetError() const;
+
+ friend class RSA;
+ friend class DSS;
+ friend class DiffieHellman;
+private:
+ struct RandomImpl;
+ RandomImpl* pimpl_;
+
+ RandomPool(const RandomPool&); // hide copy
+ RandomPool& operator=(const RandomPool&); // & assign
+};
+
+
+// Authentication policy should implement sign, and verify
+struct Auth {
+ virtual void sign(byte*, const byte*, unsigned int, const RandomPool&) = 0;
+ virtual bool verify(const byte*, unsigned int, const byte*,
+ unsigned int) = 0;
+ virtual uint get_signatureLength() const = 0;
+ virtual ~Auth() {}
+};
+
+
+// For use with NULL Authentication schemes
+struct NO_Auth : public Auth {
+ void sign(byte*, const byte*, unsigned int, const RandomPool&) {}
+ bool verify(const byte*, unsigned int, const byte*, unsigned int)
+ { return true; }
+};
+
+
+// Digitial Signature Standard scheme
+class DSS : public Auth {
+public:
+ void sign(byte*, const byte*, unsigned int, const RandomPool&);
+ bool verify(const byte*, unsigned int, const byte*, unsigned int);
+ uint get_signatureLength() const;
+ DSS(const byte*, unsigned int, bool publicKey = true);
+ ~DSS();
+private:
+ struct DSSImpl;
+ DSSImpl* pimpl_;
+
+ DSS(const DSS&);
+ DSS& operator=(const DSS&);
+};
+
+
+// RSA Authentication and exchange
+class RSA : public Auth {
+public:
+ void sign(byte*, const byte*, unsigned int, const RandomPool&);
+ bool verify(const byte*, unsigned int, const byte*, unsigned int);
+ void encrypt(byte*, const byte*, unsigned int, const RandomPool&);
+ void decrypt(byte*, const byte*, unsigned int, const RandomPool&);
+ uint get_signatureLength() const;
+ uint get_cipherLength() const;
+ RSA(const byte*, unsigned int, bool publicKey = true);
+ ~RSA();
+private:
+ struct RSAImpl;
+ RSAImpl* pimpl_;
+
+ RSA(const RSA&); // hide copy
+ RSA& operator=(const RSA&); // & assing
+};
+
+
+class Integer;
+
+// Diffie-Hellman agreement
+// hide for now TODO: figure out a way to give access to C clients p and g args
+class DiffieHellman {
+public:
+ DiffieHellman(const byte*, unsigned int, const byte*, unsigned int,
+ const byte*, unsigned int, const RandomPool& random);
+ //DiffieHellman(const char*, const RandomPool&);
+ DiffieHellman(const Integer&, const Integer&, const RandomPool&);
+ ~DiffieHellman();
+
+ DiffieHellman(const DiffieHellman&);
+ DiffieHellman& operator=(const DiffieHellman&);
+
+ uint get_agreedKeyLength() const;
+ const byte* get_agreedKey() const;
+ const byte* get_publicKey() const;
+ void makeAgreement(const byte*);
+
+ void set_sizes(int&, int&, int&) const;
+ void get_parms(byte*, byte*, byte*) const;
+private:
+ struct DHImpl;
+ DHImpl* pimpl_;
+};
+
+
+// Lagrge Integer
+class Integer {
+public:
+ Integer();
+ ~Integer();
+
+ Integer(const Integer&);
+ Integer& operator=(const Integer&);
+
+ void assign(const byte*, unsigned int);
+
+ friend class DiffieHellman;
+private:
+ struct IntegerImpl;
+ IntegerImpl* pimpl_;
+};
+
+
+class x509;
+
+x509* PemToDer(const char*, CertType);
+
+
+} // naemspace
+
+#endif // yaSSL_CRYPTO_WRAPPER_HPP
diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp
new file mode 100644
index 00000000000..96798466352
--- /dev/null
+++ b/extra/yassl/include/factory.hpp
@@ -0,0 +1,106 @@
+/* factory.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* The factory header defines an Object Factory, used by SSL message and
+ * handshake types.
+ *
+ * See Desgin Pattern in GoF and Alexandrescu's chapter in Modern C++ Design,
+ * page 208
+ */
+
+
+
+#ifndef yaSSL_FACTORY_HPP
+#define yaSSL_FACTORY_HPP
+
+#include "vector.hpp"
+#include "pair.hpp"
+#include "yassl_error.hpp"
+
+
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ #define CPP_TYPENAME
+#else
+ #define CPP_TYPENAME typename
+#endif
+
+
+namespace yaSSL {
+
+
+// Factory uses its callback map to create objects by id,
+// returning an abstract base pointer
+template<class AbstractProduct,
+ typename IdentifierType = int,
+ typename ProductCreator = AbstractProduct* (*)()
+ >
+class Factory {
+ typedef mySTL::pair<IdentifierType, ProductCreator> CallBack;
+ typedef mySTL::vector<CallBack> CallBackVector;
+
+ CallBackVector callbacks_;
+public:
+ // pass function pointer to register all callbacks upon creation
+ explicit Factory(void (*init)(Factory<AbstractProduct, IdentifierType,
+ ProductCreator>&))
+ {
+ init(*this);
+ }
+
+ // reservce place in vector before registering, used by init funcion
+ void Reserve(size_t sz)
+ {
+ callbacks_.reserve(sz);
+ }
+
+ // register callback
+ void Register(const IdentifierType& id, ProductCreator pc)
+ {
+ callbacks_.push_back(mySTL::make_pair(id, pc));
+ }
+
+ // THE Creator, returns a new object of the proper type or 0
+ AbstractProduct* CreateObject(const IdentifierType& id) const
+ {
+ const CallBack* first = callbacks_.begin();
+ const CallBack* last = callbacks_.end();
+
+ while (first != last) {
+ if (first->first == id)
+ break;
+ ++first;
+ }
+
+ if (first == callbacks_.end())
+ return 0;
+ return (first->second)();
+ }
+private:
+ Factory(const Factory&); // hide copy
+ Factory& operator=(const Factory&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_FACTORY_HPP
diff --git a/extra/yassl/include/handshake.hpp b/extra/yassl/include/handshake.hpp
new file mode 100644
index 00000000000..6261359cd58
--- /dev/null
+++ b/extra/yassl/include/handshake.hpp
@@ -0,0 +1,72 @@
+/* handshake.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* The handshake header declares function prototypes for creating and reading
+ * the various handshake messages.
+ */
+
+
+
+#ifndef yaSSL_HANDSHAKE_HPP
+#define yaSSL_HANDSHAKE_HPP
+
+#include "yassl_types.hpp"
+
+
+namespace yaSSL {
+
+// forward decls
+class SSL;
+class Finished;
+class Data;
+class Alert;
+struct Hashes;
+
+enum BufferOutput { buffered, unbuffered };
+
+void sendClientHello(SSL&);
+void sendServerHello(SSL&, BufferOutput = buffered);
+void sendServerHelloDone(SSL&, BufferOutput = buffered);
+void sendClientKeyExchange(SSL&, BufferOutput = buffered);
+void sendServerKeyExchange(SSL&, BufferOutput = buffered);
+void sendChangeCipher(SSL&, BufferOutput = buffered);
+void sendFinished(SSL&, ConnectionEnd, BufferOutput = buffered);
+void sendCertificate(SSL&, BufferOutput = buffered);
+void sendCertificateRequest(SSL&, BufferOutput = buffered);
+void sendCertificateVerify(SSL&, BufferOutput = buffered);
+int sendData(SSL&, const void*, int);
+int sendAlert(SSL& ssl, const Alert& alert);
+
+int receiveData(SSL&, Data&);
+void processReply(SSL&);
+
+void buildFinished(SSL&, Finished&, const opaque*);
+void build_certHashes(SSL&, Hashes&);
+
+void hmac(SSL&, byte*, const byte*, uint, ContentType, bool verify = false);
+void TLS_hmac(SSL&, byte*, const byte*, uint, ContentType,
+ bool verify = false);
+void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
+ const byte* label, uint labLen, const byte* seed, uint seedLen);
+
+} // naemspace
+
+#endif // yaSSL_HANDSHAKE_HPP
diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp
new file mode 100644
index 00000000000..11a623879d4
--- /dev/null
+++ b/extra/yassl/include/lock.hpp
@@ -0,0 +1,90 @@
+/* lock.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* lock.hpp provides an os specific Lock, locks mutex on entry and unlocks
+ * automatically upon exit, no-ops provided for Single Threaded
+*/
+
+#ifndef yaSSL_LOCK_HPP
+#define yaSSL_LOCK_HPP
+
+
+namespace yaSSL {
+
+
+#ifdef MULTI_THREADED
+ #ifdef WIN32
+ #include <windows.h>
+
+ class Mutex {
+ CRITICAL_SECTION cs_;
+ public:
+ Mutex();
+ ~Mutex();
+
+ class Lock;
+ friend class Lock;
+
+ class Lock {
+ Mutex& mutex_;
+ public:
+ explicit Lock(Mutex& lm);
+ ~Lock();
+ };
+ };
+ #else // WIN32
+ #include <pthread.h>
+
+ class Mutex {
+ pthread_mutex_t mutex_;
+ public:
+
+ Mutex();
+ ~Mutex();
+
+ class Lock;
+ friend class Lock;
+
+ class Lock {
+ Mutex& mutex_;
+ public:
+ explicit Lock(Mutex& lm);
+ ~Lock();
+ };
+ };
+
+ #endif // WIN32
+#else // MULTI_THREADED (WE'RE SINGLE)
+
+ class Mutex {
+ public:
+ class Lock {
+ public:
+ explicit Lock(Mutex&) {}
+ };
+ };
+
+#endif // MULTI_THREADED
+
+
+
+} // namespace
+#endif // yaSSL_LOCK_HPP
diff --git a/extra/yassl/include/log.hpp b/extra/yassl/include/log.hpp
new file mode 100644
index 00000000000..5753bb4502d
--- /dev/null
+++ b/extra/yassl/include/log.hpp
@@ -0,0 +1,58 @@
+/* log.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL log interface
+ *
+ */
+
+#ifndef yaSSL_LOG_HPP
+#define yaSSL_LOG_HPP
+
+#include "socket_wrapper.hpp"
+
+#ifdef YASSL_LOG
+#include <cstdio>
+#endif
+
+namespace yaSSL {
+
+typedef unsigned int uint;
+
+
+// Debug logger
+class Log {
+#ifdef YASSL_LOG
+ FILE* log_;
+#endif
+public:
+ explicit Log(const char* str = "yaSSL.log");
+ ~Log();
+
+ void Trace(const char*);
+ void ShowTCP(socket_t, bool ended = false);
+ void ShowData(uint, bool sent = false);
+};
+
+
+} // naemspace
+
+#endif // yaSSL_LOG_HPP
diff --git a/extra/yassl/include/openssl/crypto.h b/extra/yassl/include/openssl/crypto.h
new file mode 100644
index 00000000000..4a0c1db0df1
--- /dev/null
+++ b/extra/yassl/include/openssl/crypto.h
@@ -0,0 +1,13 @@
+/* crypto.h for openSSL */
+
+#ifndef ysSSL_crypto_h__
+#define yaSSL_crypto_h__
+
+const char* SSLeay_version(int type);
+
+#define SSLEAY_VERSION 0x0900L
+#define SSLEAY_VERSION_NUMBER SSLEAY_VERSION
+
+
+#endif /* yaSSL_crypto_h__ */
+
diff --git a/extra/yassl/include/openssl/des.h b/extra/yassl/include/openssl/des.h
new file mode 100644
index 00000000000..67be7eecfb9
--- /dev/null
+++ b/extra/yassl/include/openssl/des.h
@@ -0,0 +1 @@
+/* des.h for openssl */
diff --git a/extra/yassl/include/openssl/err.h b/extra/yassl/include/openssl/err.h
new file mode 100644
index 00000000000..054d0940509
--- /dev/null
+++ b/extra/yassl/include/openssl/err.h
@@ -0,0 +1,8 @@
+/* err.h for openssl */
+
+#ifndef ysSSL_err_h__
+#define yaSSL_err_h__
+
+
+
+#endif /* yaSSL_err_h__ */
diff --git a/extra/yassl/include/openssl/lhash.h b/extra/yassl/include/openssl/lhash.h
new file mode 100644
index 00000000000..01f8535f869
--- /dev/null
+++ b/extra/yassl/include/openssl/lhash.h
@@ -0,0 +1,2 @@
+/* lhash.h for openSSL */
+
diff --git a/extra/yassl/include/openssl/md5.h b/extra/yassl/include/openssl/md5.h
new file mode 100644
index 00000000000..a1025b92782
--- /dev/null
+++ b/extra/yassl/include/openssl/md5.h
@@ -0,0 +1 @@
+/* md5.h for openssl */
diff --git a/extra/yassl/include/openssl/opensslv.h b/extra/yassl/include/openssl/opensslv.h
new file mode 100644
index 00000000000..d932130684f
--- /dev/null
+++ b/extra/yassl/include/openssl/opensslv.h
@@ -0,0 +1,12 @@
+/* opensslv.h compatibility */
+
+#ifndef yaSSL_opensslv_h__
+#define yaSSL_opensslv_h__
+
+
+/* api version compatibility */
+#define OPENSSL_VERSION_NUMBER 0x0090700f
+
+
+#endif /* yaSSLopensslv_h__ */
+
diff --git a/extra/yassl/include/openssl/rand.h b/extra/yassl/include/openssl/rand.h
new file mode 100644
index 00000000000..df9c9020346
--- /dev/null
+++ b/extra/yassl/include/openssl/rand.h
@@ -0,0 +1,2 @@
+/* rand.h for openSSL */
+
diff --git a/extra/yassl/include/openssl/rsa.h b/extra/yassl/include/openssl/rsa.h
new file mode 100644
index 00000000000..1ab9d13b89f
--- /dev/null
+++ b/extra/yassl/include/openssl/rsa.h
@@ -0,0 +1,10 @@
+/* rsa.h for openSSL */
+
+
+#ifndef ysSSL_rsa_h__
+#define yaSSL_rsa_h__
+
+enum { RSA_F4 = 1 };
+
+
+#endif /* yaSSL_rsa_h__ */
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
new file mode 100644
index 00000000000..361918846fc
--- /dev/null
+++ b/extra/yassl/include/openssl/ssl.h
@@ -0,0 +1,400 @@
+/* ssl.h
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* ssl.h defines openssl compatibility layer
+ *
+ */
+
+#ifndef ysSSL_openssl_h__
+#define yaSSL_openssl_h__
+
+#include <stdio.h> /* ERR_print fp */
+#include "rsa.h"
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+namespace yaSSL {
+extern "C" {
+#endif
+
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+ class SSL;
+ class SSL_SESSION;
+ class SSL_METHOD;
+ class SSL_CTX;
+ class SSL_CIPHER;
+
+ class RSA;
+
+ class X509;
+ class X509_NAME;
+#else
+ typedef struct SSL SSL;
+ typedef struct SSL_SESION SSL_SESSION;
+ typedef struct SSL_METHOD SSL_METHOD;
+ typedef struct SSL_CTX SSL_CTX;
+ typedef struct SSL_CIPHER SSL_CIPHER;
+
+ typedef struct RSA RSA;
+
+ typedef struct X509 X509;
+ typedef struct X509_NAME X509_NAME;
+#endif
+
+
+/* Big Number stuff, different file? */
+typedef struct BIGNUM BIGNUM;
+
+BIGNUM *BN_bin2bn(const unsigned char*, int, BIGNUM*);
+
+
+/* Diffie-Hellman stuff, different file? */
+/* mySQL deferences to set group parameters */
+typedef struct DH {
+ BIGNUM* p;
+ BIGNUM* g;
+} DH;
+
+DH* DH_new(void);
+void DH_free(DH*);
+
+/* RSA stuff */
+
+void RSA_free(RSA*);
+RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*);
+
+
+/* X509 stuff, different file? */
+
+typedef struct X509_STORE X509_STORE;
+typedef struct X509_LOOKUP X509_LOOKUP;
+typedef struct X509_OBJECT { char c; } X509_OBJECT;
+typedef struct X509_CRL X509_CRL;
+typedef struct X509_REVOKED X509_REVOKED;
+typedef struct X509_LOOKUP_METHOD X509_LOOKUP_METHOD;
+
+
+void X509_free(X509*);
+
+
+/* bio stuff */
+typedef struct BIO BIO;
+
+/* ASN stuff */
+typedef struct ASN1_TIME ASN1_TIME;
+
+
+
+/* because mySQL dereferences to use error and current_cert, even after calling
+ * get functions for local references */
+typedef struct X509_STORE_CTX {
+ int error;
+ int error_depth;
+ X509* current_cert;
+} X509_STORE_CTX;
+
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*);
+
+char* X509_NAME_oneline(X509_NAME*, char*, int);
+X509_NAME* X509_get_issuer_name(X509*);
+X509_NAME* X509_get_subject_name(X509*);
+const char* X509_verify_cert_error_string(long);
+
+int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long);
+int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long);
+X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD* X509_LOOKUP_file(void);
+
+X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*);
+X509_STORE* X509_STORE_new(void);
+int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*,
+ X509_OBJECT*);
+
+
+
+
+enum { /* X509 Constants */
+ X509_V_OK = 0,
+ X509_V_ERR_CERT_CHAIN_TOO_LONG = 1,
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2,
+ X509_V_ERR_CERT_NOT_YET_VALID = 3,
+ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 4,
+ X509_V_ERR_CERT_HAS_EXPIRED = 5,
+ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 6,
+ X509_FILETYPE_PEM = 7,
+ X509_LU_X509 = 8,
+ X509_LU_CRL = 9,
+ X509_V_ERR_CRL_SIGNATURE_FAILURE = 10,
+ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 11,
+ X509_V_ERR_CRL_HAS_EXPIRED = 12,
+ X509_V_ERR_CERT_REVOKED = 13,
+
+};
+
+
+/* Error stuff, could move to yassl_error */
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *);
+void ERR_print_errors_fp(FILE*);
+char* ERR_error_string(unsigned long,char*);
+void ERR_remove_state(unsigned long);
+unsigned long ERR_get_error(void);
+unsigned long ERR_peek_error(void);
+int ERR_GET_REASON(int);
+
+
+enum { /* ERR Constants */
+ ERR_TXT_STRING = 1,
+ EVP_R_BAD_DECRYPT = 2,
+};
+
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD*);
+SSL* SSL_new(SSL_CTX*);
+int SSL_set_fd (SSL*, int);
+int SSL_connect(SSL*);
+int SSL_write(SSL*, const void*, int);
+int SSL_read(SSL*, void*, int);
+int SSL_accept(SSL*);
+void SSL_CTX_free(SSL_CTX*);
+void SSL_free(SSL*);
+int SSL_clear(SSL*);
+int SSL_shutdown(SSL*);
+
+void SSL_set_connect_state(SSL*);
+void SSL_set_accept_state(SSL*);
+int SSL_do_handshake(SSL*);
+
+const char* SSL_get_cipher(SSL*);
+const char* SSL_get_cipher_name(SSL*); /* uses SSL_get_cipher */
+char* SSL_get_shared_ciphers(SSL*, char*, int);
+const char* SSL_get_cipher_list(SSL*, int);
+const char* SSL_get_version(SSL*);
+const char* SSLeay_version(int);
+
+int SSL_get_error(SSL*, int);
+void SSL_load_error_strings(void);
+
+int SSL_set_session(SSL *ssl, SSL_SESSION *session);
+SSL_SESSION* SSL_get_session(SSL* ssl);
+long SSL_SESSION_set_timeout(SSL_SESSION*, long);
+X509* SSL_get_peer_certificate(SSL*);
+long SSL_get_verify_result(SSL*);
+
+
+typedef int (*VerifyCallback)(int, X509_STORE_CTX*);
+typedef int (*pem_password_cb)(char*, int, int, void*);
+
+void SSL_CTX_set_verify(SSL_CTX*, int, VerifyCallback verify_callback);
+int SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*);
+int SSL_CTX_set_default_verify_paths(SSL_CTX*);
+int SSL_CTX_check_private_key(SSL_CTX*);
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int);
+
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int));
+long SSL_CTX_set_options(SSL_CTX*, long);
+long SSL_CTX_set_session_cache_mode(SSL_CTX*, long);
+long SSL_CTX_set_timeout(SSL_CTX*, long);
+int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*);
+void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int);
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)());
+
+long SSL_CTX_sess_accept(SSL_CTX*);
+long SSL_CTX_sess_connect(SSL_CTX*);
+long SSL_CTX_sess_accept_good(SSL_CTX*);
+long SSL_CTX_sess_connect_good(SSL_CTX*);
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_hits(SSL_CTX*);
+long SSL_CTX_sess_cb_hits(SSL_CTX*);
+long SSL_CTX_sess_cache_full(SSL_CTX*);
+long SSL_CTX_sess_misses(SSL_CTX*);
+long SSL_CTX_sess_timeouts(SSL_CTX*);
+long SSL_CTX_sess_number(SSL_CTX*);
+long SSL_CTX_sess_get_cache_size(SSL_CTX*);
+
+int SSL_CTX_get_verify_mode(SSL_CTX*);
+int SSL_get_verify_mode(SSL*);
+int SSL_CTX_get_verify_depth(SSL_CTX*);
+int SSL_get_verify_depth(SSL*);
+
+long SSL_get_default_timeout(SSL*);
+long SSL_CTX_get_session_cache_mode(SSL_CTX*);
+int SSL_session_reused(SSL*);
+
+int SSL_set_rfd(SSL*, int);
+int SSL_set_wfd(SSL*, int);
+void SSL_set_shutdown(SSL*, int);
+
+int SSL_want_read(SSL*);
+int SSL_want_write(SSL*);
+
+int SSL_pending(SSL*);
+
+
+enum { /* ssl Constants */
+ SSL_BAD_FILETYPE = -5,
+ SSL_BAD_FILE = -4,
+ SSL_NOT_IMPLEMENTED = -3,
+ SSL_UNKNOWN = -2,
+ SSL_FATAL_ERROR = -1,
+ SSL_NORMAL_SHUTDOWN = 0,
+ SSL_ERROR_NONE = 0, // for most functions
+ SSL_FAILURE = 0, // for some functions
+ SSL_SUCCESS = 1,
+
+ SSL_FILETYPE_ASN1 = 10,
+ SSL_FILETYPE_PEM = 11,
+ SSL_FILETYPE_DEFAULT = 10, /* ASN1 */
+
+ SSL_VERIFY_NONE = 0,
+ SSL_VERIFY_PEER = 1,
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
+ SSL_VERIFY_CLIENT_ONCE = 4,
+
+ SSL_SESS_CACHE_OFF = 30,
+ SSL_SESS_CACHE_CLIENT = 31,
+ SSL_SESS_CACHE_SERVER = 32,
+ SSL_SESS_CACHE_BOTH = 33,
+ SSL_SESS_CACHE_NO_AUTO_CLEAR = 34,
+ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35,
+
+ SSL_OP_MICROSOFT_SESS_ID_BUG = 50,
+ SSL_OP_NETSCAPE_CHALLENGE_BUG = 51,
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 52,
+ SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 53,
+ SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 54,
+ SSL_OP_MSIE_SSLV2_RSA_PADDING = 55,
+ SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 56,
+ SSL_OP_TLS_D5_BUG = 57,
+ SSL_OP_TLS_BLOCK_PADDING_BUG = 58,
+ SSL_OP_TLS_ROLLBACK_BUG = 59,
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 60,
+ SSL_OP_ALL = 61,
+ SSL_OP_SINGLE_DH_USE = 62,
+ SSL_OP_EPHEMERAL_RSA = 63,
+ SSL_OP_NO_SSLv2 = 64,
+ SSL_OP_NO_SSLv3 = 65,
+ SSL_OP_NO_TLSv1 = 66,
+ SSL_OP_PKCS1_CHECK_1 = 67,
+ SSL_OP_PKCS1_CHECK_2 = 68,
+ SSL_OP_NETSCAPE_CA_DN_BUG = 69,
+ SSL_OP_NON_EXPORT_FIRST = 70,
+ SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 71,
+
+ SSL_ERROR_WANT_READ = 80,
+ SSL_ERROR_WANT_WRITE = 81,
+ SSL_ERROR_SYSCALL = 82,
+ SSL_ERROR_WANT_X509_LOOKUP = 83,
+ SSL_ERROR_ZERO_RETURN = 84,
+ SSL_ERROR_SSL = 85,
+
+ SSL_SENT_SHUTDOWN = 90,
+ SSL_RECEIVED_SHUTDOWN = 91,
+ SSL_CB_LOOP = 92,
+ SSL_ST_CONNECT = 93,
+ SSL_ST_ACCEPT = 94,
+ SSL_CB_ALERT = 95,
+ SSL_CB_READ = 96,
+ SSL_CB_HANDSHAKE_DONE = 97,
+
+};
+
+
+SSL_METHOD *SSLv3_method(void);
+SSL_METHOD *SSLv3_server_method(void);
+SSL_METHOD *SSLv3_client_method(void);
+SSL_METHOD *TLSv1_server_method(void);
+SSL_METHOD *TLSv1_client_method(void);
+SSL_METHOD *SSLv23_server_method(void);
+
+int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX*, const char*, int);
+int SSL_CTX_set_cipher_list(SSL_CTX*, const char*);
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX*, long);
+long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*);
+
+void OpenSSL_add_all_algorithms(void);
+void SSLeay_add_ssl_algorithms(void);
+
+
+SSL_CIPHER* SSL_get_current_cipher(SSL*);
+char* SSL_CIPHER_description(SSL_CIPHER*, char*, int);
+
+
+char* SSL_alert_type_string_long(int);
+char* SSL_alert_desc_string_long(int);
+char* SSL_state_string_long(SSL*);
+
+
+/* EVP stuff, des and md5, different file? */
+typedef struct Digest Digest;
+typedef Digest EVP_MD;
+
+typedef struct BulkCipher BulkCipher;
+typedef BulkCipher EVP_CIPHER;
+
+typedef struct EVP_PKEY EVP_PKEY;
+
+typedef unsigned char DES_cblock[8];
+typedef const DES_cblock const_DES_cblock;
+typedef DES_cblock DES_key_schedule;
+
+
+const EVP_MD* EVP_md5(void);
+const EVP_CIPHER* EVP_des_ede3_cbc(void);
+
+typedef unsigned char opaque;
+
+int EVP_BytesToKey(const EVP_CIPHER*, const EVP_MD*, const opaque*,
+ const opaque*, int, int, opaque*, opaque*);
+
+void DES_set_key_unchecked(const_DES_cblock*, DES_key_schedule*);
+void DES_ede3_cbc_encrypt(const opaque*, opaque*, long, DES_key_schedule*,
+ DES_key_schedule*, DES_key_schedule*, DES_cblock*, int);
+
+
+/* RAND stuff */
+void RAND_screen(void);
+const char* RAND_file_name(char*, size_t);
+int RAND_write_file(const char*);
+int RAND_load_file(const char*, long);
+
+
+#define SSL_DEFAULT_CIPHER_LIST "" /* default all */
+
+
+
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+} /* namespace */
+} /* extern "C" */
+#endif
+
+
+#endif /* yaSSL_openssl_h__ */
diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp
new file mode 100644
index 00000000000..dddbd65e220
--- /dev/null
+++ b/extra/yassl/include/socket_wrapper.hpp
@@ -0,0 +1,95 @@
+/* socket_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The socket wrapper header defines a Socket class that hides the differences
+ * between Berkely style sockets and Windows sockets, allowing transparent TCP
+ * access.
+ */
+
+
+#ifndef yaSSL_SOCKET_WRAPPER_HPP
+#define yaSSL_SOCKET_WRAPPER_HPP
+
+#include <cassert>
+
+#ifdef WIN32
+ #include <winsock2.h>
+#else
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+#endif
+
+
+namespace yaSSL {
+
+typedef unsigned int uint;
+
+#ifdef WIN32
+ typedef SOCKET socket_t;
+#else
+ typedef int socket_t;
+ const socket_t INVALID_SOCKET = -1;
+ const int SD_RECEIVE = 0;
+ const int SD_SEND = 1;
+ const int SD_BOTH = 2;
+ const int SOCKET_ERROR = -1;
+#endif
+
+
+
+typedef unsigned char byte;
+
+
+// Wraps Windows Sockets and BSD Sockets
+class Socket {
+ socket_t socket_; // underlying socket descriptor
+public:
+ explicit Socket(socket_t s = INVALID_SOCKET);
+ virtual ~Socket();
+
+ void set_fd(socket_t s);
+ uint get_ready() const;
+ socket_t get_fd() const;
+
+ uint send(const byte* buf, unsigned int len, int flags = 0) const;
+ uint receive(byte* buf, unsigned int len, int flags = 0) const;
+
+ void wait() const;
+
+ void closeSocket();
+ void shutDown(int how = SD_SEND);
+
+ static int get_lastError();
+ static void set_lastError(int error);
+private:
+ Socket(const Socket&); // hide copy
+ Socket& operator= (const Socket&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_SOCKET_WRAPPER_HPP
diff --git a/extra/yassl/include/timer.hpp b/extra/yassl/include/timer.hpp
new file mode 100644
index 00000000000..3025b7a0bd9
--- /dev/null
+++ b/extra/yassl/include/timer.hpp
@@ -0,0 +1,43 @@
+/* timer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* timer.hpp provides a high res and low res timers
+ *
+*/
+
+
+#ifndef yaSSL_TIMER_HPP
+#define yaSSL_TIMER_HPP
+
+namespace yaSSL {
+
+typedef double timer_d;
+typedef unsigned int uint;
+
+
+
+timer_d timer();
+uint lowResTimer();
+
+
+
+} // namespace
+#endif // yaSSL_TIMER_HPP
diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp
new file mode 100644
index 00000000000..4165eb24b66
--- /dev/null
+++ b/extra/yassl/include/yassl_error.hpp
@@ -0,0 +1,78 @@
+/* yassl_error.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL error header defines error codes and an exception class
+ */
+
+#ifndef yaSSL_ERROR_HPP
+#define yaSSL_ERROR_HPP
+
+#include "stdexcept.hpp"
+
+
+namespace yaSSL {
+
+
+enum YasslError {
+ no_error = 0,
+
+ // 10 - 47 from AlertDescription, 0 also close_notify
+
+ range_error = 101,
+ realloc_error = 102,
+ factory_error = 103,
+ unknown_cipher = 104,
+ prefix_error = 105,
+ record_layer = 106,
+ handshake_layer = 107,
+ out_of_order = 108,
+ bad_input = 109,
+ match_error = 110,
+ no_key_file = 111,
+ verify_error = 112,
+ send_error = 113,
+ receive_error = 114,
+ certificate_error = 115,
+
+ // 1000+ from TaoCrypt error.hpp
+
+};
+
+
+enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib };
+
+// Base class for all yaSSL exceptions
+class Error : public mySTL::runtime_error {
+ YasslError error_;
+ Library lib_;
+public:
+ explicit Error(const char* s = "", YasslError e = no_error,
+ Library l = yaSSL_Lib);
+
+ YasslError get_number() const;
+ Library get_lib() const;
+};
+
+
+} // naemspace
+
+#endif // yaSSL_ERROR_HPP
diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp
new file mode 100644
index 00000000000..52108b6aa1c
--- /dev/null
+++ b/extra/yassl/include/yassl_imp.hpp
@@ -0,0 +1,742 @@
+/* yassl_imp.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* yaSSL implementation header defines all strucutres from the SSL.v3
+ * specification "draft-freier-ssl-version3-02.txt"
+ * all page citations refer to this document unless otherwise noted.
+ */
+
+
+#ifndef yaSSL_IMP_HPP
+#define yaSSL_IMP_HPP
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+#include "yassl_types.hpp"
+#include "factory.hpp"
+#include "list.hpp" // mySTL::list
+
+
+namespace yaSSL {
+
+
+class SSL; // forward decls
+class input_buffer;
+class output_buffer;
+
+
+struct ProtocolVersion {
+ uint8 major_;
+ uint8 minor_; // major and minor SSL/TLS version numbers
+
+ ProtocolVersion(uint8 maj = 3, uint8 min = 0);
+};
+
+
+// Record Layer Header for PlainText, Compressed, and CipherText
+struct RecordLayerHeader {
+ ContentType type_;
+ ProtocolVersion version_;
+ uint16 length_; // should not exceed 2^14
+};
+
+
+// base for all messages
+struct Message {
+ virtual input_buffer& set(input_buffer&) =0;
+ virtual output_buffer& get(output_buffer&) const =0;
+
+ virtual void Process(input_buffer&, SSL&) =0;
+ virtual ContentType get_type() const =0;
+ virtual uint16 get_length() const =0;
+
+ virtual ~Message() {}
+};
+
+
+class ChangeCipherSpec : public Message {
+ CipherChoice type_;
+public:
+ ChangeCipherSpec();
+
+ friend input_buffer& operator>>(input_buffer&, ChangeCipherSpec&);
+ friend output_buffer& operator<<(output_buffer&, const ChangeCipherSpec&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ void Process(input_buffer&, SSL&);
+private:
+ ChangeCipherSpec(const ChangeCipherSpec&); // hide copy
+ ChangeCipherSpec& operator=(const ChangeCipherSpec&); // and assign
+};
+
+
+
+class Alert : public Message {
+ AlertLevel level_;
+ AlertDescription description_;
+public:
+ Alert() {}
+ Alert(AlertLevel al, AlertDescription ad);
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ void Process(input_buffer&, SSL&);
+
+ friend input_buffer& operator>>(input_buffer&, Alert&);
+ friend output_buffer& operator<<(output_buffer&, const Alert&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+private:
+ Alert(const Alert&); // hide copy
+ Alert& operator=(const Alert&); // and assign
+};
+
+
+class Data : public Message {
+ uint16 length_;
+ opaque* buffer_; // read buffer used by fillData input
+ const opaque* write_buffer_; // write buffer used by output operator
+public:
+ Data();
+ Data(uint16 len, opaque* b);
+ Data(uint16 len, const opaque* w);
+
+ friend output_buffer& operator<<(output_buffer&, const Data&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ const opaque* get_buffer() const;
+ void set_length(uint16 l);
+ opaque* set_buffer();
+ void Process(input_buffer&, SSL&);
+private:
+ Data(const Data&); // hide copy
+ Data& operator=(const Data&); // and assign
+};
+
+
+uint32 c24to32(const uint24); // forward form internal header
+void c32to24(uint32, uint24&);
+
+
+// HandShake header, same for each message type from page 20/21
+class HandShakeHeader : public Message {
+ HandShakeType type_;
+ uint24 length_; // length of message
+public:
+ HandShakeHeader() {}
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ HandShakeType get_handshakeType() const;
+ void Process(input_buffer&, SSL&);
+
+ void set_type(HandShakeType hst);
+ void set_length(uint32 u32);
+
+ friend input_buffer& operator>>(input_buffer&, HandShakeHeader&);
+ friend output_buffer& operator<<(output_buffer&, const HandShakeHeader&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+private:
+ HandShakeHeader(const HandShakeHeader&); // hide copy
+ HandShakeHeader& operator=(const HandShakeHeader&); // and assign
+};
+
+
+// Base Class for all handshake messages
+class HandShakeBase {
+ int length_;
+public:
+ int get_length() const;
+ void set_length(int);
+
+ // for building buffer's type field
+ virtual HandShakeType get_type() const =0;
+
+ // handles dispactch of proper >>
+ virtual input_buffer& set(input_buffer& in) =0;
+ virtual output_buffer& get(output_buffer& out) const =0;
+
+ virtual void Process(input_buffer&, SSL&) =0;
+
+ virtual ~HandShakeBase() {}
+};
+
+
+struct HelloRequest : public HandShakeBase {
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer&, SSL&);
+
+ HandShakeType get_type() const;
+};
+
+
+// The Client's Hello Message from page 23
+class ClientHello : public HandShakeBase {
+ ProtocolVersion client_version_;
+ Random random_;
+ uint8 id_len_; // session id length
+ opaque session_id_[ID_LEN];
+ uint16 suite_len_; // cipher suite length
+ opaque cipher_suites_[MAX_SUITE_SZ];
+ uint8 comp_len_; // compression length
+ CompressionMethod compression_methods_;
+public:
+ friend input_buffer& operator>>(input_buffer&, ClientHello&);
+ friend output_buffer& operator<<(output_buffer&, const ClientHello&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+
+ const opaque* get_random() const;
+ friend void buildClientHello(SSL&, ClientHello&, CompressionMethod);
+ friend void ProcessOldClientHello(input_buffer& input, SSL& ssl);
+
+ ClientHello();
+ explicit ClientHello(ProtocolVersion pv);
+private:
+ ClientHello(const ClientHello&); // hide copy
+ ClientHello& operator=(const ClientHello&); // and assign
+};
+
+
+
+// The Server's Hello Message from page 24
+class ServerHello : public HandShakeBase {
+ ProtocolVersion server_version_;
+ Random random_;
+ uint8 id_len_; // session id length
+ opaque session_id_[ID_LEN];
+ opaque cipher_suite_[SUITE_LEN];
+ CompressionMethod compression_method_;
+public:
+ explicit ServerHello(ProtocolVersion pv);
+ ServerHello();
+
+ friend input_buffer& operator>>(input_buffer&, ServerHello&);
+ friend output_buffer& operator<<(output_buffer&, const ServerHello&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+
+ const opaque* get_random() const;
+ friend void buildServerHello(SSL&, ServerHello&);
+private:
+ ServerHello(const ServerHello&); // hide copy
+ ServerHello& operator=(const ServerHello&); // and assign
+};
+
+
+class x509;
+
+// Certificate could be a chain
+class Certificate : public HandShakeBase {
+ const x509* cert_;
+public:
+ Certificate();
+ explicit Certificate(const x509* cert);
+ friend output_buffer& operator<<(output_buffer&, const Certificate&);
+
+ const opaque* get_buffer() const;
+
+ // Process handles input, needs SSL
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+private:
+ Certificate(const Certificate&); // hide copy
+ Certificate& operator=(const Certificate&); // and assign
+};
+
+
+
+// RSA Public Key
+struct ServerRSAParams {
+ opaque* rsa_modulus_;
+ opaque* rsa_exponent_;
+};
+
+
+// Ephemeral Diffie-Hellman Parameters
+class ServerDHParams {
+ int pSz_;
+ int gSz_;
+ int pubSz_;
+ opaque* p_;
+ opaque* g_;
+ opaque* Ys_;
+public:
+ ServerDHParams();
+ ~ServerDHParams();
+
+ int get_pSize() const;
+ int get_gSize() const;
+ int get_pubSize() const;
+
+ const opaque* get_p() const;
+ const opaque* get_g() const;
+ const opaque* get_pub() const;
+
+ opaque* alloc_p(int sz);
+ opaque* alloc_g(int sz);
+ opaque* alloc_pub(int sz);
+private:
+ ServerDHParams(const ServerDHParams&); // hide copy
+ ServerDHParams& operator=(const ServerDHParams&); // and assign
+};
+
+
+struct ServerKeyBase {
+ virtual ~ServerKeyBase() {}
+ virtual void build(SSL&) {}
+ virtual void read(SSL&, input_buffer&) {}
+ virtual int get_length() const;
+ virtual opaque* get_serverKey() const;
+};
+
+
+// Server random number for FORTEZZA KEA
+struct Fortezza_Server : public ServerKeyBase {
+ opaque r_s_[FORTEZZA_MAX];
+};
+
+
+struct SignatureBase {
+ virtual ~SignatureBase() {}
+};
+
+struct anonymous_sa : public SignatureBase {};
+
+
+struct Hashes {
+ uint8 md5_[MD5_LEN];
+ uint8 sha_[SHA_LEN];
+};
+
+
+struct rsa_sa : public SignatureBase {
+ Hashes hashes_;
+};
+
+
+struct dsa_sa : public SignatureBase {
+ uint8 sha_[SHA_LEN];
+};
+
+
+// Server's Diffie-Hellman exchange
+class DH_Server : public ServerKeyBase {
+ ServerDHParams parms_;
+ opaque* signature_;
+
+ int length_; // total length of message
+ opaque* keyMessage_; // total exchange message
+public:
+ DH_Server();
+ ~DH_Server();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_serverKey() const;
+private:
+ DH_Server(const DH_Server&); // hide copy
+ DH_Server& operator=(const DH_Server&); // and assign
+};
+
+
+// Server's RSA exchange
+struct RSA_Server : public ServerKeyBase {
+ ServerRSAParams params_;
+ opaque* signature_; // signed rsa_sa hashes
+};
+
+
+class ServerKeyExchange : public HandShakeBase {
+ ServerKeyBase* server_key_;
+public:
+ explicit ServerKeyExchange(SSL&);
+ ServerKeyExchange();
+ ~ServerKeyExchange();
+
+ void createKey(SSL&);
+ void build(SSL& ssl);
+
+ const opaque* getKey() const;
+ int getKeyLength() const;
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend output_buffer& operator<<(output_buffer&, const ServerKeyExchange&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+private:
+ ServerKeyExchange(const ServerKeyExchange&); // hide copy
+ ServerKeyExchange& operator=(const ServerKeyExchange&); // and assign
+};
+
+
+
+class CertificateRequest : public HandShakeBase {
+ ClientCertificateType certificate_types_[CERT_TYPES];
+ int typeTotal_;
+ mySTL::list<DistinguishedName> certificate_authorities_;
+public:
+ CertificateRequest();
+ ~CertificateRequest();
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend input_buffer& operator>>(input_buffer&, CertificateRequest&);
+ friend output_buffer& operator<<(output_buffer&,
+ const CertificateRequest&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+
+ void Build();
+private:
+ CertificateRequest(const CertificateRequest&); // hide copy
+ CertificateRequest& operator=(const CertificateRequest&); // and assign
+};
+
+
+struct ServerHelloDone : public HandShakeBase {
+ ServerHelloDone();
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer& input, SSL& ssl);
+
+ HandShakeType get_type() const;
+};
+
+
+struct PreMasterSecret {
+ opaque random_[SECRET_LEN]; // first two bytes Protocol Version
+};
+
+
+struct ClientKeyBase {
+ virtual ~ClientKeyBase() {}
+ virtual void build(SSL&) {}
+ virtual void read(SSL&, input_buffer&) {}
+ virtual int get_length() const;
+ virtual opaque* get_clientKey() const;
+};
+
+
+class EncryptedPreMasterSecret : public ClientKeyBase {
+ opaque* secret_;
+ int length_;
+public:
+ EncryptedPreMasterSecret();
+ ~EncryptedPreMasterSecret();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_clientKey() const;
+ void alloc(int sz);
+private:
+ // hide copy and assign
+ EncryptedPreMasterSecret(const EncryptedPreMasterSecret&);
+ EncryptedPreMasterSecret& operator=(const EncryptedPreMasterSecret&);
+};
+
+
+// Fortezza Key Parameters from page 29
+// hard code lengths cause only used here
+struct FortezzaKeys : public ClientKeyBase {
+ opaque y_c_ [128]; // client's Yc, public value
+ opaque r_c_ [128]; // client's Rc
+ opaque y_signature_ [40]; // DSS signed public key
+ opaque wrapped_client_write_key_ [12]; // wrapped by the TEK
+ opaque wrapped_server_write_key_ [12]; // wrapped by the TEK
+ opaque client_write_iv_ [24];
+ opaque server_write_iv_ [24];
+ opaque master_secret_iv_ [24]; // IV used to encrypt preMaster
+ opaque encrypted_preMasterSecret_[48]; // random & crypted by the TEK
+};
+
+
+
+// Diffie-Hellman public key from page 40/41
+class ClientDiffieHellmanPublic : public ClientKeyBase {
+ PublicValueEncoding public_value_encoding_;
+ int length_; // includes two byte length for message
+ opaque* Yc_; // length + Yc_
+ // dh_Yc only if explicit, otherwise sent in certificate
+ enum { KEY_OFFSET = 2 };
+public:
+ ClientDiffieHellmanPublic();
+ ~ClientDiffieHellmanPublic();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_clientKey() const;
+ void alloc(int sz, bool offset = false);
+private:
+ // hide copy and assign
+ ClientDiffieHellmanPublic(const ClientDiffieHellmanPublic&);
+ ClientDiffieHellmanPublic& operator=(const ClientDiffieHellmanPublic&);
+};
+
+
+class ClientKeyExchange : public HandShakeBase {
+ ClientKeyBase* client_key_;
+public:
+ explicit ClientKeyExchange(SSL& ssl);
+ ClientKeyExchange();
+ ~ClientKeyExchange();
+
+ void createKey(SSL&);
+ void build(SSL& ssl);
+
+ const opaque* getKey() const;
+ int getKeyLength() const;
+
+ friend output_buffer& operator<<(output_buffer&, const ClientKeyExchange&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+private:
+ ClientKeyExchange(const ClientKeyExchange&); // hide copy
+ ClientKeyExchange& operator=(const ClientKeyExchange&); // and assign
+};
+
+
+class CertificateVerify : public HandShakeBase {
+ Hashes hashes_;
+ byte* signature_; // owns
+public:
+ CertificateVerify();
+ ~CertificateVerify();
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend input_buffer& operator>>(input_buffer&, CertificateVerify&);
+ friend output_buffer& operator<<(output_buffer&, const CertificateVerify&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+
+ void Build(SSL&);
+private:
+ CertificateVerify(const CertificateVerify&); // hide copy
+ CertificateVerify& operator=(const CertificateVerify&); // and assign
+};
+
+
+class Finished : public HandShakeBase {
+ Hashes hashes_;
+public:
+ Finished();
+
+ uint8* set_md5();
+ uint8* set_sha();
+
+ friend input_buffer& operator>>(input_buffer&, Finished&);
+ friend output_buffer& operator<<(output_buffer&, const Finished&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer&, SSL&);
+
+ HandShakeType get_type() const;
+private:
+ Finished(const Finished&); // hide copy
+ Finished& operator=(const Finished&); // and assign
+};
+
+
+class RandomPool; // forward for connection
+
+
+// SSL Connection defined on page 11
+struct Connection {
+ opaque *pre_master_secret_;
+ opaque master_secret_[SECRET_LEN];
+ opaque client_random_[RAN_LEN];
+ opaque server_random_[RAN_LEN];
+ opaque sessionID_[ID_LEN];
+ opaque client_write_MAC_secret_[SHA_LEN]; // sha is max size
+ opaque server_write_MAC_secret_[SHA_LEN];
+ opaque client_write_key_[AES_256_KEY_SZ]; // aes 256bit is max sz
+ opaque server_write_key_[AES_256_KEY_SZ];
+ opaque client_write_IV_[AES_IV_SZ]; // aes is max size
+ opaque server_write_IV_[AES_IV_SZ];
+ uint32 sequence_number_;
+ uint32 peer_sequence_number_;
+ uint32 pre_secret_len_; // pre master length
+ bool send_server_key_; // server key exchange?
+ bool master_clean_; // master secret clean?
+ bool TLS_; // TLSv1 or greater
+ ProtocolVersion version_;
+ RandomPool& random_;
+
+ Connection(ProtocolVersion v, RandomPool& ran);
+ ~Connection();
+
+ void AllocPreSecret(uint sz);
+ void CleanPreMaster();
+ void CleanMaster();
+ void TurnOffTLS();
+private:
+ Connection(const Connection&); // hide copy
+ Connection& operator=(const Connection&); // and assign
+};
+
+
+struct Ciphers; // forward
+
+
+// TLSv1 Security Spec, defined on page 56 of RFC 2246
+struct Parameters {
+ ConnectionEnd entity_;
+ BulkCipherAlgorithm bulk_cipher_algorithm_;
+ CipherType cipher_type_;
+ uint8 key_size_;
+ uint8 iv_size_;
+ IsExportable is_exportable_;
+ MACAlgorithm mac_algorithm_;
+ uint8 hash_size_;
+ CompressionMethod compression_algorithm_;
+ KeyExchangeAlgorithm kea_; // yassl additions
+ SignatureAlgorithm sig_algo_; // signature auth type
+ SignatureAlgorithm verify_algo_; // cert verify auth type
+ bool pending_;
+ bool resumable_; // new conns by session
+ uint16 encrypt_size_; // current msg encrypt sz
+ Cipher suite_[SUITE_LEN]; // choosen suite
+ uint8 suites_size_;
+ Cipher suites_[MAX_SUITE_SZ];
+ char cipher_name_[MAX_SUITE_NAME];
+ char cipher_list_[MAX_CIPHER_LIST];
+
+ Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion);
+
+ void SetSuites(ProtocolVersion pv);
+ void SetCipherNames();
+private:
+ Parameters(const Parameters&); // hide copy
+ Parameters& operator=(const Parameters&); // and assing
+};
+
+
+input_buffer& operator>>(input_buffer&, RecordLayerHeader&);
+output_buffer& operator<<(output_buffer&, const RecordLayerHeader&);
+
+input_buffer& operator>>(input_buffer&, Message&);
+output_buffer& operator<<(output_buffer&, const Message&);
+
+input_buffer& operator>>(input_buffer&, HandShakeBase&);
+output_buffer& operator<<(output_buffer&, const HandShakeBase&);
+
+
+// Message Factory definition
+// uses the ContentType enumeration for unique id
+typedef Factory<Message> MessageFactory;
+void InitMessageFactory(MessageFactory&); // registers derived classes
+
+// HandShake Factory definition
+// uses the HandShakeType enumeration for unique id
+typedef Factory<HandShakeBase> HandShakeFactory;
+void InitHandShakeFactory(HandShakeFactory&); // registers derived classes
+
+// ServerKey Factory definition
+// uses KeyExchangeAlgorithm enumeration for unique id
+typedef Factory<ServerKeyBase> ServerKeyFactory;
+void InitServerKeyFactory(ServerKeyFactory&);
+
+// ClientKey Factory definition
+// uses KeyExchangeAlgorithm enumeration for unique id
+typedef Factory<ClientKeyBase> ClientKeyFactory;
+void InitClientKeyFactory(ClientKeyFactory&);
+
+
+// Message Creators
+Message* CreateHandShake();
+Message* CreateCipherSpec();
+Message* CreateAlert();
+Message* CreateData();
+
+
+// HandShake Creators
+HandShakeBase* CreateCertificate();
+HandShakeBase* CreateHelloRequest();
+HandShakeBase* CreateClientHello();
+HandShakeBase* CreateServerHello();
+HandShakeBase* CreateServerKeyExchange();
+HandShakeBase* CreateCertificateRequest();
+HandShakeBase* CreateServerHelloDone();
+HandShakeBase* CreateClientKeyExchange();
+HandShakeBase* CreateCertificateVerify();
+HandShakeBase* CreateFinished();
+
+
+// ServerKey Exchange Creators
+ServerKeyBase* CreateRSAServerKEA();
+ServerKeyBase* CreateDHServerKEA();
+ServerKeyBase* CreateFortezzaServerKEA();
+
+// ClientKey Exchange Creators
+ClientKeyBase* CreateRSAClient();
+ClientKeyBase* CreateDHClient();
+ClientKeyBase* CreateFortezzaClient();
+
+
+
+} // naemspace
+
+#endif // yaSSL_IMP_HPP
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
new file mode 100644
index 00000000000..02895d3897b
--- /dev/null
+++ b/extra/yassl/include/yassl_int.hpp
@@ -0,0 +1,540 @@
+/* yassl_int.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL internal header defines SSL supporting types not specified in the
+ * draft along with type conversion functions and openssl compatibility
+ */
+
+
+#ifndef yaSSL_INT_HPP
+#define yaSSL_INT_HPP
+
+#include "yassl_imp.hpp"
+#include "crypto_wrapper.hpp"
+#include "cert_wrapper.hpp"
+#include "lock.hpp"
+#include "log.hpp"
+
+
+namespace yaSSL {
+
+
+// State Machine for Record Layer Protocol
+enum RecordLayerState {
+ recordNotReady = 0, // fatal error, no more processing
+ recordReady
+};
+
+
+// State Machine for HandShake Protocol
+enum HandShakeState {
+ handShakeNotReady = 0, // fatal error, no more processing
+ preHandshake, // initial state
+ inHandshake, // handshake started
+ handShakeReady // handshake done
+};
+
+
+// client input HandShake state, use if HandShakeState == inHandShake
+enum ClientState {
+ serverNull = 0,
+ serverHelloComplete,
+ serverCertComplete,
+ serverKeyExchangeComplete,
+ serverHelloDoneComplete,
+ serverFinishedComplete
+};
+
+
+// server input HandShake state, use if HandShakeState == inHandShake
+enum ServerState {
+ clientNull = 0,
+ clientHelloComplete,
+ clientKeyExchangeComplete,
+ clientFinishedComplete
+};
+
+
+// combines all states
+class States {
+ enum {MAX_ERROR_SZ = 80 };
+
+ RecordLayerState recordLayer_;
+ HandShakeState handshakeLayer_;
+ ClientState clientState_;
+ ServerState serverState_;
+ char errorString_[MAX_ERROR_SZ];
+ YasslError what_;
+public:
+ States();
+
+ const RecordLayerState& getRecord() const;
+ const HandShakeState& getHandShake() const;
+ const ClientState& getClient() const;
+ const ServerState& getServer() const;
+ const char* getString() const;
+ YasslError What() const;
+
+ RecordLayerState& useRecord();
+ HandShakeState& useHandShake();
+ ClientState& useClient();
+ ServerState& useServer();
+ char* useString();
+ void SetError(YasslError);
+private:
+ States(const States&); // hide copy
+ States& operator=(const States&); // and assign
+};
+
+
+// holds all factories
+class sslFactory {
+ MessageFactory messageFactory_; // creates new messages by type
+ HandShakeFactory handShakeFactory_; // creates new handshake types
+ ServerKeyFactory serverKeyFactory_; // creates new server key types
+ ClientKeyFactory clientKeyFactory_; // creates new client key types
+
+ sslFactory(); // only GetSSL_Factory creates
+public:
+ const MessageFactory& getMessage() const;
+ const HandShakeFactory& getHandShake() const;
+ const ServerKeyFactory& getServerKey() const;
+ const ClientKeyFactory& getClientKey() const;
+
+ friend sslFactory& GetSSL_Factory(); // singleton creator
+private:
+ static sslFactory instance;
+ sslFactory(const sslFactory&); // hide copy
+ sslFactory& operator=(const sslFactory&); // and assign
+};
+
+
+// openSSL X509 names
+class X509_NAME {
+ char* name_;
+public:
+ X509_NAME(const char*, size_t sz);
+ ~X509_NAME();
+
+ char* GetName();
+private:
+ X509_NAME(const X509_NAME&); // hide copy
+ X509_NAME& operator=(const X509_NAME&); // and assign
+};
+
+
+// openSSL X509
+class X509 {
+ X509_NAME issuer_;
+ X509_NAME subject_;
+public:
+ X509(const char* i, size_t, const char* s, size_t);
+ ~X509() {}
+
+ X509_NAME* GetIssuer();
+ X509_NAME* GetSubject();
+private:
+ X509(const X509&); // hide copy
+ X509& operator=(const X509&); // and assign
+};
+
+
+// openSSL bignum
+struct BIGNUM {
+ Integer int_;
+ void assign(const byte* b, uint s) { int_.assign(b,s); }
+};
+
+
+// openSSL session
+class SSL_SESSION {
+ opaque sessionID_[ID_LEN];
+ opaque master_secret_[SECRET_LEN];
+ Cipher suite_[SUITE_LEN];
+ uint bornOn_; // create time in seconds
+ uint timeout_; // timeout in seconds
+ RandomPool& random_; // will clean master secret
+public:
+ explicit SSL_SESSION(RandomPool&);
+ SSL_SESSION(const SSL&, RandomPool&);
+ ~SSL_SESSION();
+
+ const opaque* GetID() const;
+ const opaque* GetSecret() const;
+ const Cipher* GetSuite() const;
+ uint GetBornOn() const;
+ uint GetTimeOut() const;
+ void SetTimeOut(uint);
+
+ SSL_SESSION& operator=(const SSL_SESSION&); // allow assign for resumption
+private:
+ SSL_SESSION(const SSL_SESSION&); // hide copy
+};
+
+
+// holds all sessions
+class Sessions {
+ mySTL::list<SSL_SESSION*> list_;
+ RandomPool random_; // for session cleaning
+ Mutex mutex_; // no-op for single threaded
+
+ Sessions() {} // only GetSessions can create
+public:
+ SSL_SESSION* lookup(const opaque*, SSL_SESSION* copy = 0);
+ void add(const SSL&);
+ void remove(const opaque*);
+
+ ~Sessions();
+
+ friend Sessions& GetSessions(); // singleton creator
+private:
+ Sessions(const Sessions&); // hide copy
+ Sessions& operator=(const Sessions&); // and assign
+ static Sessions instance;
+};
+
+
+Sessions& GetSessions(); // forward singletons
+sslFactory& GetSSL_Factory();
+
+
+// openSSL method and context types
+class SSL_METHOD {
+ ProtocolVersion version_;
+ ConnectionEnd side_;
+ bool verifyPeer_;
+ bool failNoCert_;
+public:
+ explicit SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv);
+
+ ProtocolVersion getVersion() const;
+ ConnectionEnd getSide() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+
+ bool verifyPeer() const;
+ bool failNoCert() const;
+private:
+ SSL_METHOD(const SSL_METHOD&); // hide copy
+ SSL_METHOD& operator=(const SSL_METHOD&); // and assign
+};
+
+
+struct Ciphers {
+ bool setSuites_; // user set suites from default
+ byte suites_[MAX_SUITE_SZ]; // new suites
+ int suiteSz_; // suite length in bytes
+
+ Ciphers() : setSuites_(false), suiteSz_(0) {}
+};
+
+
+struct DH; // forward
+
+
+// save for SSL construction
+struct DH_Parms {
+ Integer p_;
+ Integer g_;
+ bool set_; // if set by user
+
+ DH_Parms() : set_(false) {}
+};
+
+
+enum StatsField {
+ Accept, Connect, AcceptGood, ConnectGood, AcceptRenegotiate,
+ ConnectRenegotiate, Hits, CbHits, CacheFull, Misses, Timeouts, Number,
+ GetCacheSize, VerifyMode, VerifyDepth
+};
+
+
+// SSL stats
+struct Stats {
+ long accept_;
+ long connect_;
+ long acceptGood_;
+ long connectGood_;
+ long acceptRenegotiate_;
+ long connectRenegotiate_;
+
+ long hits_;
+ long cbHits_;
+ long cacheFull_;
+ long misses_;
+ long timeouts_;
+ long number_;
+ long getCacheSize_;
+
+ int verifyMode_;
+ int verifyDepth_;
+public:
+ Stats() : accept_(0), connect_(0), acceptGood_(0), connectGood_(0),
+ acceptRenegotiate_(0), connectRenegotiate_(0), hits_(0), cbHits_(0),
+ cacheFull_(0), misses_(0), timeouts_(0), number_(0), getCacheSize_(0),
+ verifyMode_(0), verifyDepth_(0)
+ {}
+private:
+ Stats(const Stats&); // hide copy
+ Stats& operator=(const Stats&); // and assign
+};
+
+
+// the SSL context
+class SSL_CTX {
+public:
+ typedef mySTL::list<x509*> CertList;
+private:
+ SSL_METHOD* method_;
+ x509* certificate_;
+ x509* privateKey_;
+ CertList caList_;
+ Ciphers ciphers_;
+ DH_Parms dhParms_;
+ Stats stats_;
+ Mutex mutex_; // for Stats
+public:
+ explicit SSL_CTX(SSL_METHOD* meth);
+ ~SSL_CTX();
+
+ const x509* getCert() const;
+ const x509* getKey() const;
+ const SSL_METHOD* getMethod() const;
+ const Ciphers& GetCiphers() const;
+ const DH_Parms& GetDH_Parms() const;
+ const Stats& GetStats() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+ bool SetCipherList(const char*);
+ bool SetDH(const DH&);
+
+ void IncrementStats(StatsField);
+ void AddCA(x509* ca);
+ const CertList& GetCA_List() const;
+
+ friend int read_file(SSL_CTX*, const char*, int, CertType);
+private:
+ SSL_CTX(const SSL_CTX&); // hide copy
+ SSL_CTX& operator=(const SSL_CTX&); // and assign
+};
+
+
+// holds all cryptographic types
+class Crypto {
+ Digest* digest_; // agreed upon digest
+ BulkCipher* cipher_; // agreed upon cipher
+ DiffieHellman* dh_; // dh parms
+ RandomPool random_; // random number generator
+ CertManager cert_; // manages certificates
+public:
+ explicit Crypto();
+ ~Crypto();
+
+ const Digest& get_digest() const;
+ const BulkCipher& get_cipher() const;
+ const DiffieHellman& get_dh() const;
+ const RandomPool& get_random() const;
+ const CertManager& get_certManager() const;
+
+ Digest& use_digest();
+ BulkCipher& use_cipher();
+ DiffieHellman& use_dh();
+ RandomPool& use_random();
+ CertManager& use_certManager();
+
+ void SetDH(DiffieHellman*);
+ void SetDH(const DH_Parms&);
+ void setDigest(Digest*);
+ void setCipher(BulkCipher*);
+
+ bool DhSet();
+private:
+ Crypto(const Crypto&); // hide copy
+ Crypto& operator=(const Crypto&); // and assign
+};
+
+
+// holds all handshake and verify hashes
+class sslHashes {
+ MD5 md5HandShake_; // md5 handshake hash
+ SHA shaHandShake_; // sha handshake hash
+ Finished verify_; // peer's verify hash
+ Hashes certVerify_; // peer's cert verify hash
+public:
+ sslHashes() {}
+
+ const MD5& get_MD5() const;
+ const SHA& get_SHA() const;
+ const Finished& get_verify() const;
+ const Hashes& get_certVerify() const;
+
+ MD5& use_MD5();
+ SHA& use_SHA();
+ Finished& use_verify();
+ Hashes& use_certVerify();
+private:
+ sslHashes(const sslHashes&); // hide copy
+ sslHashes& operator=(const sslHashes&); // and assign
+};
+
+
+// holds input and output buffers
+class Buffers {
+ typedef mySTL::list<input_buffer*> inputList;
+ typedef mySTL::list<output_buffer*> outputList;
+
+ inputList dataList_; // list of users app data / handshake
+ outputList handShakeList_; // buffered handshake msgs
+public:
+ Buffers() {}
+ ~Buffers();
+
+ const inputList& getData() const;
+ const outputList& getHandShake() const;
+
+ inputList& useData();
+ outputList& useHandShake();
+private:
+ Buffers(const Buffers&); // hide copy
+ Buffers& operator=(const Buffers&); // and assign
+};
+
+
+// wraps security parameters
+class Security {
+ Connection conn_; // connection information
+ Parameters parms_; // may be pending
+ SSL_SESSION resumeSession_; // if resuming
+ SSL_CTX* ctx_; // context used to init
+ bool resuming_; // trying to resume
+public:
+ Security(ProtocolVersion, RandomPool&, ConnectionEnd, const Ciphers&,
+ SSL_CTX*);
+
+ const SSL_CTX* GetContext() const;
+ const Connection& get_connection() const;
+ const Parameters& get_parms() const;
+ const SSL_SESSION& get_resume() const;
+ bool get_resuming() const;
+
+ Connection& use_connection();
+ Parameters& use_parms();
+ SSL_SESSION& use_resume();
+
+ void set_resuming(bool b);
+private:
+ Security(const Security&); // hide copy
+ Security& operator=(const Security&); // and assign
+};
+
+
+// THE SSL type
+class SSL {
+ Crypto crypto_; // agreed crypto agents
+ Security secure_; // Connection and Session parms
+ States states_; // Record and HandShake states
+ sslHashes hashes_; // handshake, finished hashes
+ Socket socket_; // socket wrapper
+ Buffers buffers_; // buffered handshakes and data
+ Log log_; // logger
+public:
+ SSL(SSL_CTX* ctx);
+
+ // gets and uses
+ const Crypto& getCrypto() const;
+ const Security& getSecurity() const;
+ const States& getStates() const;
+ const sslHashes& getHashes() const;
+ const sslFactory& getFactory() const;
+ const Socket& getSocket() const;
+ YasslError GetError() const;
+
+ Crypto& useCrypto();
+ Security& useSecurity();
+ States& useStates();
+ sslHashes& useHashes();
+ Socket& useSocket();
+ Log& useLog();
+
+ // sets
+ void set_pending(Cipher suite);
+ void set_random(const opaque*, ConnectionEnd);
+ void set_sessionID(const opaque*);
+ void set_session(SSL_SESSION*);
+ void set_preMaster(const opaque*, uint);
+ void set_masterSecret(const opaque*);
+ void SetError(YasslError);
+
+ // helpers
+ bool isTLS() const;
+ void order_error();
+ void makeMasterSecret();
+ void makeTLSMasterSecret();
+ void addData(input_buffer* data);
+ void fillData(Data&);
+ void addBuffer(output_buffer* b);
+ void flushBuffer();
+ void verifyState(const RecordLayerHeader&);
+ void verifyState(const HandShakeHeader&);
+ void verifyState(ClientState);
+ void verifyState(ServerState);
+ void verfiyHandShakeComplete();
+ void matchSuite(const opaque*, uint length);
+ void deriveKeys();
+ void deriveTLSKeys();
+ void Send(const byte*, uint);
+
+ uint bufferedData();
+ uint get_SEQIncrement(bool);
+
+ const byte* get_macSecret(bool);
+private:
+ void storeKeys(const opaque*);
+ void setKeys();
+ void verifyClientState(HandShakeType);
+ void verifyServerState(HandShakeType);
+
+ SSL(const SSL&); // hide copy
+ const SSL& operator=(const SSL&); // and assign
+};
+
+
+
+// conversion functions
+void c32to24(uint32, uint24&);
+void c24to32(const uint24, uint32&);
+
+uint32 c24to32(const uint24);
+
+void ato16(const opaque*, uint16&);
+void ato24(const opaque*, uint24&);
+
+void c16toa(uint16, opaque*);
+void c24toa(const uint24, opaque*);
+void c32toa(uint32 u32, opaque*);
+
+
+} // naemspace
+
+#endif // yaSSL_INT_HPP
diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp
new file mode 100644
index 00000000000..70888f35c81
--- /dev/null
+++ b/extra/yassl/include/yassl_types.hpp
@@ -0,0 +1,415 @@
+/* yassl_types.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* yaSSL types header defines all constants, enums, and typedefs
+ * from the SSL.v3 specification "draft-freier-ssl-version3-02.txt"
+ */
+
+
+#ifndef yaSSL_TYPES_HPP
+#define yaSSL_TYPES_HPP
+
+#include<cstddef>
+
+namespace yaSSL {
+
+// library allocation
+struct new_t {}; // yaSSL New type
+extern new_t ys; // pass in parameter
+
+} // namespace yaSSL
+
+void* operator new (size_t, yaSSL::new_t);
+void* operator new[](size_t, yaSSL::new_t);
+
+namespace yaSSL {
+
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef uint8 uint24[3];
+typedef uint32 uint64[2];
+
+typedef uint8 opaque;
+typedef opaque byte;
+
+typedef unsigned int uint;
+
+
+// all length constants in bytes
+const int ID_LEN = 32; // session id length
+const int SUITE_LEN = 2; // cipher suite length
+const int SECRET_LEN = 48; // pre RSA and all master secret length
+const int MASTER_ROUNDS = 3; // master secret derivation rounds
+const int RAN_LEN = 32; // client and server random length
+const int MAC_BLOCK_SZ = 64; // MAC block size, & padding
+const int MD5_LEN = 16; // MD5 digest length
+const int SHA_LEN = 20; // SHA digest length
+const int RMD_LEN = 20; // RIPEMD-160 digest length
+const int PREFIX = 3; // up to 3 prefix letters for secret rounds
+const int KEY_PREFIX = 7; // up to 7 prefix letters for key rounds
+const int FORTEZZA_MAX = 128; // Maximum Fortezza Key length
+const int MAX_SUITE_SZ = 64; // 32 max suites * sizeof(suite)
+const int MAX_SUITE_NAME = 48; // max length of suite name
+const int MAX_CIPHER_LIST = 512; // max length of cipher list names
+const int SIZEOF_ENUM = 1; // SSL considers an enum 1 byte, not 4
+const int SIZEOF_SENDER = 4; // Sender constant, for finished generation
+const int PAD_MD5 = 48; // pad length 1 and 2 for md5 finished
+const int PAD_SHA = 40; // should be 44, specd wrong by netscape
+const int PAD_RMD = 44; // pad length for RIPEMD-160, some use 40??
+const int CERT_HEADER = 3; // always use 3 bytes for certificate
+const int CERT_TYPES = 7; // certificate request types
+const int REQUEST_HEADER = 2; // request uses 2 bytes
+const int VERIFY_HEADER = 2; // verify length field
+const int MIN_CERT_TYPES = 1; // minimum certificate request types
+const int MIN_DIS_NAMES = 3; // minimum distinguished names
+const int MIN_DIS_SIZE = 1; // minimum distinguished name size
+const int RECORD_HEADER = 5; // type + version + length(2)
+const int HANDSHAKE_HEADER = 4; // type + length(3)
+const int FINISHED_SZ = MD5_LEN + SHA_LEN; // sizeof finished data
+const int TLS_FINISHED_SZ = 12; // TLS verify data size
+const int SEQ_SZ = 8; // 64 bit sequence number
+const int LENGTH_SZ = 2; // length field for HMAC, data only
+const int VERSION_SZ = SIZEOF_ENUM * 2; // SSL/TLS length of version
+const int DES_KEY_SZ = 8; // DES Key length
+const int DES_EDE_KEY_SZ = 24; // DES EDE Key length
+const int DES_BLOCK = 8; // DES is always fixed block size 8
+const int DES_IV_SZ = DES_BLOCK; // Init Vector length for DES
+const int RC4_KEY_SZ = 16; // RC4 Key length
+const int AES_128_KEY_SZ = 16; // AES 128bit Key length
+const int AES_256_KEY_SZ = 32; // AES 256bit Key length
+const int AES_BLOCK_SZ = 16; // AES 128bit block size, rfc 3268
+const int AES_IV_SZ = AES_BLOCK_SZ; // AES Init Vector length
+const int DSS_SIG_SZ = 40; // two 20 byte high byte first Integers
+const int DSS_ENCODED_EXTRA = 6; // seqID + len(1) + (intID + len(1)) * 2
+const int EVP_SALT_SZ = 8;
+const int MASTER_LABEL_SZ = 13; // TLS master secret label size
+const int KEY_LABEL_SZ = 13; // TLS key block expansion size
+const int FINISHED_LABEL_SZ = 15; // TLS finished lable length
+const int SEED_LEN = RAN_LEN * 2; // TLS seed, client + server random
+const int DEFAULT_TIMEOUT = 500; // Default Session timeout in seconds
+const int MAX_RECORD_SIZE = 16384; // 2^14, max size by standard
+
+
+typedef uint8 Cipher; // first byte is always 0x00 for SSLv3 & TLS
+
+typedef opaque Random[RAN_LEN];
+
+typedef opaque* DistinguishedName;
+
+typedef bool IsExportable;
+
+
+enum CompressionMethod { no_compression = 0 };
+
+enum CipherType { stream, block };
+
+enum CipherChoice { change_cipher_spec_choice = 1 };
+
+enum PublicValueEncoding { implicit_encoding, explicit_encoding };
+
+enum ConnectionEnd { server_end, client_end };
+
+enum AlertLevel { warning = 1, fatal = 2, };
+
+
+
+// Record Layer Header identifier from page 12
+enum ContentType {
+ no_type = 0,
+ change_cipher_spec = 20,
+ alert = 21,
+ handshake = 22,
+ application_data = 23
+};
+
+
+// HandShake Layer Header identifier from page 20
+enum HandShakeType {
+ no_shake = -1,
+ hello_request = 0,
+ client_hello = 1,
+ server_hello = 2,
+ certificate = 11,
+ server_key_exchange = 12,
+ certificate_request = 13,
+ server_hello_done = 14,
+ certificate_verify = 15,
+ client_key_exchange = 16,
+ finished = 20
+};
+
+
+// Valid Alert types from page 16/17
+enum AlertDescription {
+ close_notify = 0,
+ unexpected_message = 10,
+ bad_record_mac = 20,
+ decompression_failure = 30,
+ handshake_failure = 40,
+ no_certificate = 41,
+ bad_certificate = 42,
+ unsupported_certificate = 43,
+ certificate_revoked = 44,
+ certificate_expired = 45,
+ certificate_unknown = 46,
+ illegal_parameter = 47
+};
+
+
+// Supported Key Exchange Protocols
+enum KeyExchangeAlgorithm {
+ no_kea = 0,
+ rsa_kea,
+ diffie_hellman_kea,
+ fortezza_kea
+};
+
+
+// Supported Authentication Schemes
+enum SignatureAlgorithm {
+ anonymous_sa_algo = 0,
+ rsa_sa_algo,
+ dsa_sa_algo
+};
+
+
+// Valid client certificate request types from page 27
+enum ClientCertificateType {
+ rsa_sign = 1,
+ dss_sign = 2,
+ rsa_fixed_dh = 3,
+ dss_fixed_dh = 4,
+ rsa_ephemeral_dh = 5,
+ dss_ephemeral_dh = 6,
+ fortezza_kea_cert = 20
+};
+
+
+// Supported Ciphers from page 43
+enum BulkCipherAlgorithm {
+ cipher_null,
+ rc4,
+ rc2,
+ des,
+ triple_des, // leading 3 (3des) not valid identifier
+ des40,
+ idea,
+ aes
+};
+
+
+// Supported Message Authentication Codes from page 43
+enum MACAlgorithm {
+ no_mac,
+ md5,
+ sha,
+ rmd
+};
+
+
+// Certificate file Type
+enum CertType { Cert = 0, PrivateKey, CA };
+
+
+// all Cipher Suites from pages 41/42
+const Cipher SSL_NULL_WITH_NULL_NULL = 0; // { 0x00, 0x00 }
+const Cipher SSL_RSA_WITH_NULL_MD5 = 1; // { 0x00, 0x01 }
+const Cipher SSL_RSA_WITH_NULL_SHA = 2; // { 0x00, 0x02 }
+const Cipher SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3; // { 0x00, 0x03 }
+const Cipher SSL_RSA_WITH_RC4_128_MD5 = 4; // { 0x00, 0x04 }
+const Cipher SSL_RSA_WITH_RC4_128_SHA = 5; // { 0x00, 0x05 }
+const Cipher SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6; // { 0x00, 0x06 }
+const Cipher SSL_RSA_WITH_IDEA_CBC_SHA = 7; // { 0x00, 0x07 }
+const Cipher SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8; // { 0x00, 0x08 }
+const Cipher SSL_RSA_WITH_DES_CBC_SHA = 9; // { 0x00, 0x09 }
+const Cipher SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10; // { 0x00, 0x0A }
+const Cipher SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11; // { 0x00, 0x0B }
+const Cipher SSL_DH_DSS_WITH_DES_CBC_SHA = 12; // { 0x00, 0x0C }
+const Cipher SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13; // { 0x00, 0x0D }
+const Cipher SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14; // { 0x00, 0x0E }
+const Cipher SSL_DH_RSA_WITH_DES_CBC_SHA = 15; // { 0x00, 0x0F }
+const Cipher SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16; // { 0x00, 0x10 }
+const Cipher SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17; // { 0x00, 0x11 }
+const Cipher SSL_DHE_DSS_WITH_DES_CBC_SHA = 18; // { 0x00, 0x12 }
+const Cipher SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19; // { 0x00, 0x13 }
+const Cipher SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20; // { 0x00, 0x14 }
+const Cipher SSL_DHE_RSA_WITH_DES_CBC_SHA = 21; // { 0x00, 0x15 }
+const Cipher SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22; // { 0x00, 0x16 }
+const Cipher SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23; // { 0x00, 0x17 }
+const Cipher SSL_DH_anon_WITH_RC4_128_MD5 = 24; // { 0x00, 0x18 }
+const Cipher SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25; // { 0x00, 0x19 }
+const Cipher SSL_DH_anon_WITH_DES_CBC_SHA = 26; // { 0x00, 0x1A }
+const Cipher SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27; // { 0x00, 0x1B }
+const Cipher SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28; // { 0x00, 0x1C }
+const Cipher SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29; // { 0x00, 0x1D }
+const Cipher SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30; // { 0x00, 0x1E }
+
+// .. to 0x2B uses Kerberos Authentication
+
+
+// TLS AES extensions
+const Cipher TLS_RSA_WITH_AES_128_CBC_SHA = 47; // { 0x00, 0x2F }
+const Cipher TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48; // { 0x00, 0x30 }
+const Cipher TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49; // { 0x00, 0x31 }
+const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50; // { 0x00, 0x32 }
+const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51; // { 0x00, 0x33 }
+const Cipher TLS_DH_anon_WITH_AES_128_CBC_SHA = 52; // { 0x00, 0x34 }
+
+const Cipher TLS_RSA_WITH_AES_256_CBC_SHA = 53; // { 0x00, 0x35 }
+const Cipher TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54; // { 0x00, 0x36 }
+const Cipher TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55; // { 0x00, 0x37 }
+const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56; // { 0x00, 0x38 }
+const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57; // { 0x00, 0x39 }
+const Cipher TLS_DH_anon_WITH_AES_256_CBC_SHA = 58; // { 0x00, 0x3A }
+
+
+// OpenPGP extensions
+
+const Cipher TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114; // { 0x00, 0x72 };
+const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115; // { 0x00, 0x73 };
+const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116; // { 0x00, 0x74 };
+const Cipher TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119; // { 0x00, 0x77 };
+const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120; // { 0x00, 0x78 };
+const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121; // { 0x00, 0x79 };
+const Cipher TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124; // { 0x00, 0x7C };
+const Cipher TLS_RSA_WITH_AES_128_CBC_RMD160 = 125; // { 0x00, 0x7D };
+const Cipher TLS_RSA_WITH_AES_256_CBC_RMD160 = 126; // { 0x00, 0x7E };
+
+
+const char* const null_str = "";
+
+const char* const cipher_names[128] =
+{
+ null_str, // SSL_NULL_WITH_NULL_NULL = 0
+ null_str, // SSL_RSA_WITH_NULL_MD5 = 1
+ null_str, // SSL_RSA_WITH_NULL_SHA = 2
+ null_str, // SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3
+ "RC4-MD5", // SSL_RSA_WITH_RC4_128_MD5 = 4
+ "RC4-SHA", // SSL_RSA_WITH_RC4_128_SHA = 5
+ null_str, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6
+ null_str, // SSL_RSA_WITH_IDEA_CBC_SHA = 7
+ null_str, // SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8
+ "DES-CBC-SHA", // SSL_RSA_WITH_DES_CBC_SHA = 9
+ "DES-CBC3-SHA", // SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10
+
+ null_str, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11
+ null_str, // SSL_DH_DSS_WITH_DES_CBC_SHA = 12
+ null_str, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13
+ null_str, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14
+ null_str, // SSL_DH_RSA_WITH_DES_CBC_SHA = 15
+ null_str, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16
+ null_str, // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17
+ "EDH-DSS-DES-CBC-SHA", // SSL_DHE_DSS_WITH_DES_CBC_SHA = 18
+ "EDH-DSS-DES-CBC3-SHA", // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19
+ null_str, // SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20
+
+ "EDH-RSA-DES-CBC-SHA", // SSL_DHE_RSA_WITH_DES_CBC_SHA = 21
+ "EDH-RSA-DES-CBC3-SHA", // SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22
+ null_str, // SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23
+ null_str, // SSL_DH_anon_WITH_RC4_128_MD5 = 24
+ null_str, // SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25
+ null_str, // SSL_DH_anon_WITH_DES_CBC_SHA = 26
+ null_str, // SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27
+ null_str, // SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28
+ null_str, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29
+ null_str, // SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30
+
+ null_str, null_str, null_str, null_str, null_str, // 31 - 35
+ null_str, null_str, null_str, null_str, null_str, // 36 - 40
+ null_str, null_str, null_str, null_str, null_str, // 41 - 45
+ null_str, // 46
+
+ // TLS AES extensions
+ "AES128-SHA", // TLS_RSA_WITH_AES_128_CBC_SHA = 47
+ null_str, // TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48
+ null_str, // TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49
+ "DHE-DSS-AES128-SHA", // TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50
+ "DHE-RSA-AES128-SHA", // TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51
+ null_str, // TLS_DH_anon_WITH_AES_128_CBC_SHA = 52
+
+ "AES256-SHA", // TLS_RSA_WITH_AES_256_CBC_SHA = 53
+ null_str, // TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54
+ null_str, // TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55
+ "DHE-DSS-AES256-SHA", // TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56
+ "DHE-RSA-AES256-SHA", // TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57
+ null_str, // TLS_DH_anon_WITH_AES_256_CBC_SHA = 58
+
+ null_str, // 59
+ null_str, // 60
+ null_str, null_str, null_str, null_str, null_str, // 61 - 65
+ null_str, null_str, null_str, null_str, null_str, // 66 - 70
+ null_str, null_str, null_str, null_str, null_str, // 71 - 75
+ null_str, null_str, null_str, null_str, null_str, // 76 - 80
+ null_str, null_str, null_str, null_str, null_str, // 81 - 85
+ null_str, null_str, null_str, null_str, null_str, // 86 - 90
+ null_str, null_str, null_str, null_str, null_str, // 91 - 95
+ null_str, null_str, null_str, null_str, null_str, // 96 - 100
+ null_str, null_str, null_str, null_str, null_str, // 101 - 105
+ null_str, null_str, null_str, null_str, null_str, // 106 - 110
+ null_str, null_str, null_str, // 111 - 113
+
+ "DHE-DSS-DES-CBC3-RMD", // TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114
+ "DHE-DSS-AES128-RMD", // TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115
+ "DHE-DSS-AES256-RMD", // TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116
+ null_str, // 117
+ null_str, // 118
+ "DHE-RSA-DES-CBC3-RMD", // TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119
+ "DHE-RSA-AES128-RMD", // TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120
+ "DHE-RSA-AES256-RMD", // TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121
+ null_str, // 122
+ null_str, // 123
+ "DES-CBC3-RMD", // TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124
+ "AES128-RMD", // TLS_RSA_WITH_AES_128_CBC_RMD160 = 125
+ "AES256-RMD", // TLS_RSA_WITH_AES_256_CBC_RMD160 = 126
+ null_str, // 127
+};
+
+// fill with MD5 pad size since biggest required
+const opaque PAD1[PAD_MD5] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+ };
+const opaque PAD2[PAD_MD5] = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+ };
+
+const opaque client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
+const opaque server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
+
+const opaque tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
+const opaque tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
+
+const opaque master_label[MASTER_LABEL_SZ + 1] = "master secret";
+const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion";
+
+
+} // naemspace
+
+#endif // yaSSL_TYPES_HPP
diff --git a/extra/yassl/mySTL/algorithm.hpp b/extra/yassl/mySTL/algorithm.hpp
new file mode 100644
index 00000000000..3ceb0ca5fdc
--- /dev/null
+++ b/extra/yassl/mySTL/algorithm.hpp
@@ -0,0 +1,111 @@
+/* mySTL algorithm.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL algorithm implements max, min, for_each, swap, find_if, copy,
+ * copy_backward, fill
+ */
+
+#ifndef mySTL_ALGORITHM_HPP
+#define mySTL_ALGORITHM_HPP
+
+
+namespace mySTL {
+
+
+template<typename T>
+inline const T& max(const T& a, const T&b)
+{
+ return a < b ? b : a;
+}
+
+
+template<typename T>
+inline const T& min(const T& a, const T&b)
+{
+ return b < a ? b : a;
+}
+
+
+template<typename InIter, typename Func>
+Func for_each(InIter first, InIter last, Func op)
+{
+ while (first != last) {
+ op(*first);
+ ++first;
+ }
+ return op;
+}
+
+
+template<typename T>
+inline void swap(T& a, T& b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+
+template<typename InIter, typename Pred>
+InIter find_if(InIter first, InIter last, Pred pred)
+{
+ while (first != last && !pred(*first))
+ ++first;
+ return first;
+}
+
+
+template<typename InputIter, typename OutputIter>
+inline OutputIter copy(InputIter first, InputIter last, OutputIter place)
+{
+ while (first != last) {
+ *place = *first;
+ ++first;
+ ++place;
+ }
+ return place;
+}
+
+
+template<typename InputIter, typename OutputIter>
+inline OutputIter
+copy_backward(InputIter first, InputIter last, OutputIter place)
+{
+ while (first != last)
+ *--place = *--last;
+ return place;
+}
+
+
+template<typename InputIter, typename T>
+void fill(InputIter first, InputIter last, const T& v)
+{
+ while (first != last) {
+ *first = v;
+ ++first;
+ }
+}
+
+
+} // namespace mySTL
+
+#endif // mySTL_ALGORITHM_HPP
diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp
new file mode 100644
index 00000000000..1b62d60cd2e
--- /dev/null
+++ b/extra/yassl/mySTL/helpers.hpp
@@ -0,0 +1,94 @@
+/* mySTL helpers.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL helpers implements misc constructs for vector and list
+ *
+ */
+
+#ifndef mySTL_HELPERS_HPP
+#define mySTL_HELPERS_HPP
+
+#include <cstdlib>
+
+
+namespace mySTL {
+
+
+template <typename T, typename T2>
+inline void construct(T* p, const T2& value)
+{
+ new (static_cast<void*>(p)) T(value);
+}
+
+
+template <typename T>
+inline void construct(T* p)
+{
+ new (static_cast<void*>(p)) T();
+}
+
+
+template <typename T>
+inline void destroy(T* p)
+{
+ p->~T();
+}
+
+
+template <typename Iter>
+void destroy(Iter first, Iter last)
+{
+ while (first != last) {
+ destroy(&*first);
+ ++first;
+ }
+}
+
+
+template <typename Iter, typename PlaceIter>
+PlaceIter uninit_copy(Iter first, Iter last, PlaceIter place)
+{
+ while (first != last) {
+ construct(&*place, *first);
+ ++first;
+ ++place;
+ }
+ return place;
+}
+
+
+template <typename PlaceIter, typename Size, typename T>
+PlaceIter uninit_fill_n(PlaceIter place, Size n, const T& value)
+{
+ while (n) {
+ construct(&*place, value);
+ --n;
+ ++place;
+ }
+ return place;
+}
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_HELPERS_HPP
diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/mySTL/list.hpp
new file mode 100644
index 00000000000..5bbec6ab7c6
--- /dev/null
+++ b/extra/yassl/mySTL/list.hpp
@@ -0,0 +1,374 @@
+/* mySTL list.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL list implements a simple list
+ *
+ */
+
+#ifndef mySTL_LIST_HPP
+#define mySTL_LIST_HPP
+
+
+#include "helpers.hpp"
+#include <new> // ::operator new and delete, placement too
+
+
+namespace mySTL {
+
+
+
+template<typename T>
+class list {
+ struct node {
+ node(T t) : prev_(0), next_(0), value_(t) {}
+
+ node* prev_;
+ node* next_;
+ T value_;
+ };
+public:
+ list() : head_(0), tail_(0), sz_(0) {}
+ ~list();
+
+ void push_front(T);
+ void pop_front();
+ T front() const;
+ void push_back(T);
+ void pop_back();
+ T back() const;
+ bool remove(T);
+ size_t size() const { return sz_; }
+ bool empty() const { return sz_ == 0; }
+
+ class iterator {
+ node* current_;
+ public:
+ iterator() : current_(0) {}
+ explicit iterator(node* p) : current_(p) {}
+
+ T& operator*() const
+ {
+ return current_->value_;
+ }
+
+ T* operator->() const
+ {
+ return &(operator*());
+ }
+
+ iterator& operator++()
+ {
+ current_ = current_->next_;
+ return *this;
+ }
+
+ iterator& operator--()
+ {
+ current_ = current_->prev_;
+ return *this;
+ }
+
+ iterator& operator++(int)
+ {
+ iterator tmp = *this;
+ current_ = current_->next_;
+ return *this;
+ }
+
+ iterator& operator--(int)
+ {
+ iterator tmp = *this;
+ current_ = current_->prev_;
+ return *this;
+ }
+
+ bool operator==(const iterator& other) const
+ {
+ return current_ == other.current_;
+ }
+
+ bool operator!=(const iterator& other) const
+ {
+ return current_ != other.current_;
+ }
+
+ friend class list<T>;
+ };
+
+ bool erase(iterator);
+
+ iterator begin() const { return iterator(head_); }
+ iterator rbegin() const { return iterator(tail_); }
+ iterator end() const { return iterator(); }
+
+ typedef iterator const_iterator; // for now
+
+ class underflow {};
+ class overflow {};
+private:
+ node* head_;
+ node* tail_;
+ size_t sz_;
+
+ node* look_up(T);
+
+ list(const list&); // hide copy
+ list& operator=(const list&); // and assign
+};
+
+
+template<typename T>
+list<T>::~list()
+{
+ node* start = head_;
+ node* next_;
+
+ for (; start; start = next_) {
+ next_ = start->next_;
+ destroy(start);
+ ::operator delete(start);
+ }
+}
+
+
+template<typename T>
+void list<T>::push_front(T t)
+{
+ void* mem = ::operator new(sizeof(node));
+ if (!mem) abort();
+ node* add = new (mem) node(t);
+
+ if (head_) {
+ add->next_ = head_;
+ head_->prev_ = add;
+ }
+ else
+ tail_ = add;
+
+ head_ = add;
+ ++sz_;
+}
+
+
+template<typename T>
+void list<T>::pop_front()
+{
+ node* front = head_;
+
+ if (head_ == 0)
+ return;
+ else if (head_ == tail_)
+ head_ = tail_ = 0;
+ else {
+ head_ = head_->next_;
+ head_->prev_ = 0;
+ }
+ destroy(front);
+ ::operator delete(front);
+ --sz_;
+}
+
+
+template<typename T>
+T list<T>::front() const
+{
+ if (head_ == 0) return 0;
+ return head_->value_;
+}
+
+
+template<typename T>
+void list<T>::push_back(T t)
+{
+ void* mem = ::operator new(sizeof(node));
+ if (!mem) abort();
+ node* add = new (mem) node(t);
+
+ if (tail_) {
+ tail_->next_ = add;
+ add->prev_ = tail_;
+ }
+ else
+ head_ = add;
+
+ tail_ = add;
+ ++sz_;
+}
+
+
+template<typename T>
+void list<T>::pop_back()
+{
+ node* rear = tail_;
+
+ if (tail_ == 0)
+ return;
+ else if (tail_ == head_)
+ tail_ = head_ = 0;
+ else {
+ tail_ = tail_->prev_;
+ tail_->next_ = 0;
+ }
+ destroy(rear);
+ ::operator delete(rear);
+ --sz_;
+}
+
+
+template<typename T>
+T list<T>::back() const
+{
+ if (tail_ == 0) return 0;
+ return tail_->value_;
+}
+
+
+template<typename T>
+typename list<T>::node* list<T>::look_up(T t)
+{
+ node* list = head_;
+
+ if (list == 0) return 0;
+
+ for (; list; list = list->next_)
+ if (list->value_ == t)
+ return list;
+
+ return 0;
+}
+
+
+template<typename T>
+bool list<T>::remove(T t)
+{
+ node* del = look_up(t);
+
+ if (del == 0)
+ return false;
+ else if (del == head_)
+ pop_front();
+ else if (del == tail_)
+ pop_back();
+ else {
+ del->prev_->next_ = del->next_;
+ del->next_->prev_ = del->prev_;
+
+ destroy(del);
+ ::operator delete(del);
+ --sz_;
+ }
+ return true;
+}
+
+
+template<typename T>
+bool list<T>::erase(iterator iter)
+{
+ node* del = iter.current_;
+
+ if (del == 0)
+ return false;
+ else if (del == head_)
+ pop_front();
+ else if (del == tail_)
+ pop_back();
+ else {
+ del->prev_->next_ = del->next_;
+ del->next_->prev_ = del->prev_;
+
+ destroy(del);
+ ::operator delete(del);
+ --sz_;
+ }
+ return true;
+}
+
+
+/* MSVC can't handle ??
+
+template<typename T>
+T& list<T>::iterator::operator*() const
+{
+ return current_->value_;
+}
+
+
+template<typename T>
+T* list<T>::iterator::operator->() const
+{
+ return &(operator*());
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator++()
+{
+ current_ = current_->next_;
+ return *this;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator--()
+{
+ current_ = current_->prev_;
+ return *this;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator++(int)
+{
+ iterator tmp = *this;
+ current_ = current_->next_;
+ return tmp;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator--(int)
+{
+ iterator tmp = *this;
+ current_ = current_->prev_;
+ return tmp;
+}
+
+
+template<typename T>
+bool list<T>::iterator::operator==(const iterator& other) const
+{
+ return current_ == other.current_;
+}
+
+
+template<typename T>
+bool list<T>::iterator::operator!=(const iterator& other) const
+{
+ return current_ != other.current_;
+}
+*/ // end MSVC 6 can't handle
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_LIST_HPP
diff --git a/extra/yassl/mySTL/memory.hpp b/extra/yassl/mySTL/memory.hpp
new file mode 100644
index 00000000000..4049ed80813
--- /dev/null
+++ b/extra/yassl/mySTL/memory.hpp
@@ -0,0 +1,127 @@
+/* mySTL memory.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL memory implements auto_ptr
+ *
+ */
+
+#ifndef mySTL_MEMORY_HPP
+#define mySTL_MEMORY_HPP
+
+
+#ifdef _MSC_VER
+ // disable operator-> warning for builtins
+ #pragma warning(disable:4284)
+#endif
+
+
+namespace mySTL {
+
+
+template<typename T>
+struct auto_ptr_ref {
+ T* ptr_;
+ explicit auto_ptr_ref(T* p) : ptr_(p) {}
+};
+
+
+template<typename T>
+class auto_ptr {
+ T* ptr_;
+public:
+ explicit auto_ptr(T* p = 0) : ptr_(p) {}
+ ~auto_ptr()
+ {
+ delete ptr_;
+ }
+
+
+ auto_ptr(auto_ptr& other) : ptr_(other.release()) {}
+ auto_ptr& operator=(auto_ptr& that)
+ {
+ if (this != &that) {
+ delete ptr_;
+ ptr_ = that.release();
+ }
+ return *this;
+ }
+
+
+ T* operator->() const
+ {
+ return ptr_;
+ }
+
+ T& operator*() const
+ {
+ return *ptr_;
+ }
+
+ T* get() const
+ {
+ return ptr_;
+ }
+
+ T* release()
+ {
+ T* tmp = ptr_;
+ ptr_ = 0;
+ return tmp;
+ }
+
+ void reset(T* p = 0)
+ {
+ if (ptr_ != p) {
+ delete ptr_;
+ ptr_ = p;
+ }
+ }
+
+ // auto_ptr_ref conversions
+ auto_ptr(auto_ptr_ref<T> ref) : ptr_(ref.ptr_) {}
+
+ auto_ptr& operator=(auto_ptr_ref<T> ref)
+ {
+ if (this->ptr_ != ref.ptr_) {
+ delete ptr_;
+ ptr_ = ref.ptr_;
+ }
+ return *this;
+ }
+
+ template<typename T2>
+ operator auto_ptr<T2>()
+ {
+ return auto_ptr<T2>(this->release());
+ }
+
+ template<typename T2>
+ operator auto_ptr_ref<T2>()
+ {
+ return auto_ptr_ref<T2>(this->release());
+ }
+};
+
+
+} // namespace mySTL
+
+#endif // mySTL_MEMORY_HPP
diff --git a/extra/yassl/mySTL/pair.hpp b/extra/yassl/mySTL/pair.hpp
new file mode 100644
index 00000000000..c9bb03b5953
--- /dev/null
+++ b/extra/yassl/mySTL/pair.hpp
@@ -0,0 +1,61 @@
+/* mySTL pair.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL pair implements pair
+ *
+ */
+
+#ifndef mySTL_PAIR_HPP
+#define mySTL_PAIR_HPP
+
+
+
+namespace mySTL {
+
+
+template<typename T1, typename T2>
+struct pair {
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ first_type first;
+ second_type second;
+
+ pair() {}
+ pair(const T1& t1, const T2& t2) : first(t1), second(t2) {}
+
+ template<typename U1, typename U2>
+ pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
+};
+
+
+template<typename T1, typename T2>
+inline pair<T1, T2> make_pair(const T1& a, const T2& b)
+{
+ return pair<T1, T2>(a, b);
+}
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_PAIR_HPP
diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/mySTL/stdexcept.hpp
new file mode 100644
index 00000000000..817861438a5
--- /dev/null
+++ b/extra/yassl/mySTL/stdexcept.hpp
@@ -0,0 +1,72 @@
+/* mySTL stdexcept.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL memory implements exception, runtime_error
+ *
+ */
+
+#ifndef mySTL_STDEXCEPT_HPP
+#define mySTL_STDEXCEPT_HPP
+
+
+#include <cstring> // strncpy
+
+
+namespace mySTL {
+
+
+class exception {
+public:
+ exception() {}
+ virtual ~exception() {}
+
+ virtual const char* what() const { return ""; }
+};
+
+
+class named_exception : public exception {
+public:
+ enum { NAME_SIZE = 80 };
+
+ explicit named_exception(const char* str)
+ {
+ strncpy(name_, str, NAME_SIZE);
+ name_[NAME_SIZE - 1] = 0;
+ }
+
+ virtual const char* what() const { return name_; }
+private:
+ char name_[NAME_SIZE];
+};
+
+
+class runtime_error : public named_exception {
+public:
+ explicit runtime_error(const char* str) : named_exception(str) {}
+};
+
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_STDEXCEPT_HPP
diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/mySTL/vector.hpp
new file mode 100644
index 00000000000..7f1f99295e4
--- /dev/null
+++ b/extra/yassl/mySTL/vector.hpp
@@ -0,0 +1,154 @@
+/* mySTL vector.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL vector implements simple vector, w/ swap
+ *
+ */
+
+#ifndef mySTL_VECTOR_HPP
+#define mySTL_VECTOR_HPP
+
+
+#include "helpers.hpp" // construct, destory, fill, etc.
+#include "algorithm.hpp" // swap
+#include <new> // ::operator new and delete, placement too
+#include <cassert> // assert
+
+
+namespace mySTL {
+
+
+template <typename T>
+struct vector_base {
+ T* start_;
+ T* finish_;
+ T* end_of_storage_;
+
+ vector_base() : start_(0), finish_(0), end_of_storage_(0) {}
+ vector_base(size_t n)
+ {
+ start_ = static_cast<T*>(::operator new(n * sizeof(T)));
+ if (!start_) abort();
+ finish_ = start_;
+ end_of_storage_ = start_ + n;
+ }
+
+ ~vector_base() { ::operator delete(start_); }
+
+ void Swap(vector_base& that)
+ {
+ swap(start_, that.start_);
+ swap(finish_, that.finish_);
+ swap(end_of_storage_, that.end_of_storage_);
+ }
+};
+
+
+
+template <typename T>
+class vector {
+public:
+ vector() {}
+ explicit vector(size_t n) : vec_(n)
+ {
+ vec_.finish_ = uninit_fill_n(vec_.start_, n, T());
+ }
+
+ ~vector() { destroy(vec_.start_, vec_.finish_); }
+
+ vector(const vector& other) : vec_(other.size())
+ {
+ vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_,
+ vec_.start_);
+ }
+
+ size_t capacity() const { return vec_.end_of_storage_ - vec_.start_; }
+
+ size_t size() const { return vec_.finish_ - vec_.start_; }
+
+ T& operator[](size_t idx) { return *(vec_.start_ + idx); }
+ const T& operator[](size_t idx) const { return *(vec_.start_ + idx); }
+
+ const T* begin() const { return vec_.start_; }
+ const T* end() const { return vec_.finish_; }
+
+ void push_back(const T& v)
+ {
+ if (vec_.finish_ != vec_.end_of_storage_) {
+ construct(vec_.finish_, v);
+ ++vec_.finish_;
+ }
+ else {
+ vector tmp(size() * 2 + 1, *this);
+ construct(tmp.vec_.finish_, v);
+ ++tmp.vec_.finish_;
+ Swap(tmp);
+ }
+ }
+
+ void resize(size_t n, const T& v)
+ {
+ if (n == size()) return;
+
+ if (n < size()) {
+ T* first = vec_.start_ + n;
+ destroy(first, vec_.finish_);
+ vec_.finish_ -= vec_.finish_ - first;
+ }
+ else {
+ vector tmp(n, *this);
+ tmp.vec_.finish_ = uninit_fill_n(tmp.vec_.finish_, n - size(), v);
+ Swap(tmp);
+ }
+ }
+
+ void reserve(size_t n)
+ {
+ if (capacity() < n) {
+ vector tmp(n, *this);
+ Swap(tmp);
+ }
+ }
+
+ void Swap(vector& that)
+ {
+ vec_.Swap(that.vec_);
+ }
+private:
+ vector_base<T> vec_;
+
+ vector& operator=(const vector&); // hide assign
+
+ // for growing, n must be bigger than other size
+ vector(size_t n, const vector& other) : vec_(n)
+ {
+ assert(n > other.size());
+ vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_,
+ vec_.start_);
+ }
+};
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_VECTOR_HPP
diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am
new file mode 100644
index 00000000000..3dbd7bac03a
--- /dev/null
+++ b/extra/yassl/src/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I../include -I../taocrypt/include -I../mySTL
+
+noinst_LIBRARIES = libyassl.a
+libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \
+ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \
+ timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp
+EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h
diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp
new file mode 100644
index 00000000000..c97103c6f6d
--- /dev/null
+++ b/extra/yassl/src/buffer.cpp
@@ -0,0 +1,280 @@
+/* buffer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL buffer header implements input/output buffers to simulate streaming
+ * with SSL types and sockets
+ */
+
+#include "runtime.hpp"
+#include "buffer.hpp"
+#include "yassl_types.hpp"
+
+namespace yaSSL {
+
+
+
+// Checking Policy should implement a check function that tests whether the
+// index is within the size limit of the array
+
+void Check::check(uint i, uint limit)
+{
+ assert(i < limit);
+}
+
+
+void NoCheck::check(uint, uint)
+{
+}
+
+
+/* input_buffer operates like a smart c style array with a checking option,
+ * meant to be read from through [] with AUTO index or read().
+ * Should only write to at/near construction with assign() or raw (e.g., recv)
+ * followed by add_size with the number of elements added by raw write.
+ *
+ * Not using vector because need checked []access, offset, and the ability to
+ * write to the buffer bulk wise and have the correct size
+ */
+
+
+input_buffer::input_buffer()
+ : size_(0), current_(0), buffer_(0), end_(0)
+{}
+
+
+input_buffer::input_buffer(uint s)
+ : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{}
+
+
+// with assign
+input_buffer::input_buffer(uint s, const byte* t, uint len)
+ : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{
+ assign(t, len);
+}
+
+
+input_buffer::~input_buffer()
+{
+ delete [] buffer_;
+}
+
+
+// users can pass defualt zero length buffer and then allocate
+void input_buffer::allocate(uint s)
+{
+ assert(!buffer_); // find realloc error
+ buffer_ = new (ys) byte[s];
+ end_ = buffer_ + s;
+}
+
+
+// for passing to raw writing functions at beginning, then use add_size
+byte* input_buffer::get_buffer() const
+{
+ return buffer_;
+}
+
+
+// after a raw write user can set new size
+// if you know the size before the write use assign()
+void input_buffer::add_size(uint i)
+{
+ check(size_ + i-1, get_capacity());
+ size_ += i;
+}
+
+
+uint input_buffer::get_capacity() const
+{
+ return end_ - buffer_;
+}
+
+
+uint input_buffer::get_current() const
+{
+ return current_;
+}
+
+
+uint input_buffer::get_size() const
+{
+ return size_;
+}
+
+
+uint input_buffer::get_remaining() const
+{
+ return size_ - current_;
+}
+
+
+void input_buffer::set_current(uint i)
+{
+ if (i)
+ check(i - 1, size_);
+ current_ = i;
+}
+
+
+// read only access through [], advance current
+// user passes in AUTO index for ease of use
+const byte& input_buffer::operator[](uint i)
+{
+ assert (i == AUTO);
+ check(current_, size_);
+ return buffer_[current_++];
+}
+
+
+// end of input test
+bool input_buffer::eof()
+{
+ return current_ >= size_;
+}
+
+
+// peek ahead
+byte input_buffer::peek() const
+{
+ return buffer_[current_];
+}
+
+
+// write function, should use at/near construction
+void input_buffer::assign(const byte* t, uint s)
+{
+ check(current_, get_capacity());
+ add_size(s);
+ memcpy(&buffer_[current_], t, s);
+}
+
+
+// use read to query input, adjusts current
+void input_buffer::read(byte* dst, uint length)
+{
+ check(current_ + length - 1, size_);
+ memcpy(dst, &buffer_[current_], length);
+ current_ += length;
+}
+
+
+
+/* output_buffer operates like a smart c style array with a checking option.
+ * Meant to be written to through [] with AUTO index or write().
+ * Size (current) counter increases when written to. Can be constructed with
+ * zero length buffer but be sure to allocate before first use.
+ * Don't use add write for a couple bytes, use [] instead, way less overhead.
+ *
+ * Not using vector because need checked []access and the ability to
+ * write to the buffer bulk wise and retain correct size
+ */
+
+
+output_buffer::output_buffer()
+ : current_(0), buffer_(0), end_(0)
+{}
+
+
+// with allocate
+output_buffer::output_buffer(uint s)
+ : current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{}
+
+
+// with assign
+output_buffer::output_buffer(uint s, const byte* t, uint len)
+ : current_(0), buffer_(new (ys) byte[s]), end_(buffer_+ s)
+{
+ write(t, len);
+}
+
+
+output_buffer::~output_buffer()
+{
+ delete [] buffer_;
+}
+
+
+uint output_buffer::get_size() const
+{
+ return current_;
+}
+
+
+uint output_buffer::get_capacity() const
+{
+ return end_ - buffer_;
+}
+
+
+void output_buffer::set_current(uint c)
+{
+ check(c, get_capacity());
+ current_ = c;
+}
+
+
+// users can pass defualt zero length buffer and then allocate
+void output_buffer::allocate(uint s)
+{
+ assert(!buffer_); // find realloc error
+ buffer_ = new (ys) byte[s]; end_ = buffer_ + s;
+}
+
+
+// for passing to reading functions when finished
+const byte* output_buffer::get_buffer() const
+{
+ return buffer_;
+}
+
+
+// allow write access through [], update current
+// user passes in AUTO as index for ease of use
+byte& output_buffer::operator[](uint i)
+{
+ assert(i == AUTO);
+ check(current_, get_capacity());
+ return buffer_[current_++];
+}
+
+
+// end of output test
+bool output_buffer::eof()
+{
+ return current_ >= get_capacity();
+}
+
+
+void output_buffer::write(const byte* t, uint s)
+{
+ check(current_ + s - 1, get_capacity());
+ memcpy(&buffer_[current_], t, s);
+ current_ += s;
+}
+
+
+
+} // naemspace
+
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
new file mode 100644
index 00000000000..ab3cb471990
--- /dev/null
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -0,0 +1,318 @@
+/* cert_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The certificate wrapper source implements certificate management functions
+ *
+ */
+
+#include "runtime.hpp"
+#include "cert_wrapper.hpp"
+#include "yassl_int.hpp"
+
+#if defined(USE_CML_LIB)
+ #include "cmapi_cpp.h"
+#else
+ #include "asn.hpp"
+ #include "file.hpp"
+#endif // USE_CML_LIB
+
+
+namespace yaSSL {
+
+
+x509::x509(uint sz) : length_(sz), buffer_(new (ys) opaque[sz])
+{
+}
+
+
+x509::~x509()
+{
+ delete [] buffer_;
+}
+
+
+x509::x509(const x509& that) : length_(that.length_),
+ buffer_(new (ys) opaque[length_])
+{
+ memcpy(buffer_, that.buffer_, length_);
+}
+
+
+void x509::Swap(x509& that)
+{
+ mySTL::swap(length_, that.length_);
+ mySTL::swap(buffer_, that.buffer_);
+}
+
+
+x509& x509::operator=(const x509& that)
+{
+ x509 temp(that);
+ Swap(temp);
+ return *this;
+}
+
+
+uint x509::get_length() const
+{
+ return length_;
+}
+
+
+const opaque* x509::get_buffer() const
+{
+ return buffer_;
+}
+
+
+opaque* x509::use_buffer()
+{
+ return buffer_;
+}
+
+
+//CertManager
+CertManager::CertManager()
+ : peerX509_(0), verifyPeer_(false), failNoCert_(false), sendVerify_(false)
+{}
+
+
+CertManager::~CertManager()
+{
+ delete peerX509_;
+
+ mySTL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ;
+
+ mySTL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ;
+
+ mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ;
+}
+
+
+bool CertManager::verifyPeer() const
+{
+ return verifyPeer_;
+}
+
+
+bool CertManager::failNoCert() const
+{
+ return failNoCert_;
+}
+
+
+bool CertManager::sendVerify() const
+{
+ return sendVerify_;
+}
+
+
+void CertManager::setVerifyPeer()
+{
+ verifyPeer_ = true;
+}
+
+
+void CertManager::setFailNoCert()
+{
+ failNoCert_ = true;
+}
+
+
+void CertManager::setSendVerify()
+{
+ sendVerify_ = true;
+}
+
+
+void CertManager::AddPeerCert(x509* x)
+{
+ peerList_.push_back(x); // take ownership
+}
+
+
+void CertManager::CopySelfCert(const x509* x)
+{
+ if (x)
+ list_.push_back(new (ys) x509(*x));
+}
+
+
+// add to signers
+int CertManager::CopyCaCert(const x509* x)
+{
+ TaoCrypt::Source source(x->get_buffer(), x->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (!cert.GetError().What()) {
+ const TaoCrypt::PublicKey& key = cert.GetPublicKey();
+ signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ cert.GetCommonName(), cert.GetHash()));
+ }
+ return cert.GetError().What();
+}
+
+
+const x509* CertManager::get_cert() const
+{
+ return list_.front();
+}
+
+
+const opaque* CertManager::get_peerKey() const
+{
+ return peerPublicKey_.get_buffer();
+}
+
+
+X509* CertManager::get_peerX509() const
+{
+ return peerX509_;
+}
+
+
+SignatureAlgorithm CertManager::get_peerKeyType() const
+{
+ return peerKeyType_;
+}
+
+
+SignatureAlgorithm CertManager::get_keyType() const
+{
+ return keyType_;
+}
+
+
+uint CertManager::get_peerKeyLength() const
+{
+ return peerPublicKey_.get_size();
+}
+
+
+const opaque* CertManager::get_privateKey() const
+{
+ return privateKey_.get_buffer();
+}
+
+
+uint CertManager::get_privateKeyLength() const
+{
+ return privateKey_.get_size();
+}
+
+
+// Validate the peer's certificate list, from root to peer (last to first)
+int CertManager::Validate()
+{
+ CertList::iterator last = peerList_.rbegin(); // fix this
+ int count = peerList_.size();
+
+ while ( count > 1 ) {
+ TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (int err = cert.GetError().What())
+ return err;
+
+ const TaoCrypt::PublicKey& key = cert.GetPublicKey();
+ signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ cert.GetCommonName(), cert.GetHash()));
+ --last;
+ --count;
+ }
+
+ if (count) {
+ // peer's is at the front
+ TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (int err = cert.GetError().What())
+ return err;
+
+ uint sz = cert.GetPublicKey().size();
+ peerPublicKey_.allocate(sz);
+ peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz);
+
+ if (cert.GetKeyType() == TaoCrypt::RSAk)
+ peerKeyType_ = rsa_sa_algo;
+ else
+ peerKeyType_ = dsa_sa_algo;
+
+ int iSz = cert.GetIssuer() ? strlen(cert.GetIssuer()) + 1 : 0;
+ int sSz = cert.GetCommonName() ? strlen(cert.GetCommonName()) + 1 : 0;
+ peerX509_ = new (ys) X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
+ sSz);
+ }
+ return 0;
+}
+
+
+// Set the private key
+int CertManager::SetPrivateKey(const x509& key)
+{
+ privateKey_.allocate(key.get_length());
+ privateKey_.assign(key.get_buffer(), key.get_length());
+
+ // set key type
+ if (x509* cert = list_.front()) {
+ TaoCrypt::Source source(cert->get_buffer(), cert->get_length());
+ TaoCrypt::CertDecoder cert(source, false);
+ cert.DecodeToKey();
+ if (int err = cert.GetError().What())
+ return err;
+ if (cert.GetKeyType() == TaoCrypt::RSAk)
+ keyType_ = rsa_sa_algo;
+ else
+ keyType_ = dsa_sa_algo;
+ }
+ return 0;
+}
+
+
+#if defined(USE_CML_LIB)
+
+// Get the peer's certificate, extract and save public key
+void CertManager::SetPeerKey()
+{
+ // first cert is the peer's
+ x509* main = peerList_.front();
+
+ Bytes_struct cert;
+ cert.num = main->get_length();
+ cert.data = main->set_buffer();
+
+ CML::Certificate cm(cert);
+ const CML::ASN::Cert& raw = cm.base();
+ CTIL::CSM_Buffer key = raw.pubKeyInfo.key;
+
+ uint sz;
+ opaque* key_buffer = reinterpret_cast<opaque*>(key.Get(sz));
+ peerPublicKey_.allocate(sz);
+ peerPublicKey_.assign(key_buffer, sz);
+}
+
+
+#endif // USE_CML_LIB
+
+
+
+} // namespace
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
new file mode 100644
index 00000000000..c083c56f313
--- /dev/null
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -0,0 +1,978 @@
+/* crypto_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* The crypto wrapper source implements the policies for the cipher
+ * components used by SSL.
+ *
+ * The implementation relies on a specfic library, taoCrypt.
+ */
+
+#if !defined(USE_CRYPTOPP_LIB)
+
+#include "runtime.hpp"
+#include "crypto_wrapper.hpp"
+#include "cert_wrapper.hpp"
+
+#include "md5.hpp"
+#include "sha.hpp"
+#include "ripemd.hpp"
+#include "hmac.hpp"
+#include "modes.hpp"
+#include "des.hpp"
+#include "arc4.hpp"
+#include "aes.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "dh.hpp"
+#include "random.hpp"
+#include "file.hpp"
+#include "coding.hpp"
+
+
+namespace yaSSL {
+
+
+// MD5 Implementation
+struct MD5::MD5Impl {
+ TaoCrypt::MD5 md5_;
+ MD5Impl() {}
+ explicit MD5Impl(const TaoCrypt::MD5& md5) : md5_(md5) {}
+};
+
+
+MD5::MD5() : pimpl_(new (ys) MD5Impl) {}
+
+
+MD5::~MD5() { delete pimpl_; }
+
+
+MD5::MD5(const MD5& that) : Digest(), pimpl_(new (ys)
+ MD5Impl(that.pimpl_->md5_)) {}
+
+
+MD5& MD5::operator=(const MD5& that)
+{
+ pimpl_->md5_ = that.pimpl_->md5_;
+ return *this;
+}
+
+
+uint MD5::get_digestSize() const
+{
+ return MD5_LEN;
+}
+
+
+uint MD5::get_padSize() const
+{
+ return PAD_MD5;
+}
+
+
+// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz
+void MD5::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->md5_.Update(in, sz);
+ pimpl_->md5_.Final(out);
+}
+
+// Fill out with MD5 digest from previous updates
+void MD5::get_digest(byte* out)
+{
+ pimpl_->md5_.Final(out);
+}
+
+
+// Update the current digest
+void MD5::update(const byte* in, unsigned int sz)
+{
+ pimpl_->md5_.Update(in, sz);
+}
+
+
+// SHA Implementation
+struct SHA::SHAImpl {
+ TaoCrypt::SHA sha_;
+ SHAImpl() {}
+ explicit SHAImpl(const TaoCrypt::SHA& sha) : sha_(sha) {}
+};
+
+
+SHA::SHA() : pimpl_(new (ys) SHAImpl) {}
+
+
+SHA::~SHA() { delete pimpl_; }
+
+
+SHA::SHA(const SHA& that) : Digest(), pimpl_(new (ys)
+ SHAImpl(that.pimpl_->sha_)) {}
+
+SHA& SHA::operator=(const SHA& that)
+{
+ pimpl_->sha_ = that.pimpl_->sha_;
+ return *this;
+}
+
+
+uint SHA::get_digestSize() const
+{
+ return SHA_LEN;
+}
+
+
+uint SHA::get_padSize() const
+{
+ return PAD_SHA;
+}
+
+
+// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz
+void SHA::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->sha_.Update(in, sz);
+ pimpl_->sha_.Final(out);
+}
+
+
+// Fill out with SHA digest from previous updates
+void SHA::get_digest(byte* out)
+{
+ pimpl_->sha_.Final(out);
+}
+
+
+// Update the current digest
+void SHA::update(const byte* in, unsigned int sz)
+{
+ pimpl_->sha_.Update(in, sz);
+}
+
+
+// RMD-160 Implementation
+struct RMD::RMDImpl {
+ TaoCrypt::RIPEMD160 rmd_;
+ RMDImpl() {}
+ explicit RMDImpl(const TaoCrypt::RIPEMD160& rmd) : rmd_(rmd) {}
+};
+
+
+RMD::RMD() : pimpl_(new (ys) RMDImpl) {}
+
+
+RMD::~RMD() { delete pimpl_; }
+
+
+RMD::RMD(const RMD& that) : Digest(), pimpl_(new (ys)
+ RMDImpl(that.pimpl_->rmd_)) {}
+
+RMD& RMD::operator=(const RMD& that)
+{
+ pimpl_->rmd_ = that.pimpl_->rmd_;
+ return *this;
+}
+
+
+uint RMD::get_digestSize() const
+{
+ return RMD_LEN;
+}
+
+
+uint RMD::get_padSize() const
+{
+ return PAD_RMD;
+}
+
+
+// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz
+void RMD::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->rmd_.Update(in, sz);
+ pimpl_->rmd_.Final(out);
+}
+
+
+// Fill out with RMD digest from previous updates
+void RMD::get_digest(byte* out)
+{
+ pimpl_->rmd_.Final(out);
+}
+
+
+// Update the current digest
+void RMD::update(const byte* in, unsigned int sz)
+{
+ pimpl_->rmd_.Update(in, sz);
+}
+
+
+// HMAC_MD5 Implementation
+struct HMAC_MD5::HMAC_MD5Impl {
+ TaoCrypt::HMAC<TaoCrypt::MD5> mac_;
+ HMAC_MD5Impl() {}
+};
+
+
+HMAC_MD5::HMAC_MD5(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_MD5Impl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_MD5::~HMAC_MD5() { delete pimpl_; }
+
+
+uint HMAC_MD5::get_digestSize() const
+{
+ return MD5_LEN;
+}
+
+
+uint HMAC_MD5::get_padSize() const
+{
+ return PAD_MD5;
+}
+
+
+// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz
+void HMAC_MD5::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with MD5 digest from previous updates
+void HMAC_MD5::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_MD5::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+// HMAC_SHA Implementation
+struct HMAC_SHA::HMAC_SHAImpl {
+ TaoCrypt::HMAC<TaoCrypt::SHA> mac_;
+ HMAC_SHAImpl() {}
+};
+
+
+HMAC_SHA::HMAC_SHA(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_SHAImpl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_SHA::~HMAC_SHA() { delete pimpl_; }
+
+
+uint HMAC_SHA::get_digestSize() const
+{
+ return SHA_LEN;
+}
+
+
+uint HMAC_SHA::get_padSize() const
+{
+ return PAD_SHA;
+}
+
+
+// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz
+void HMAC_SHA::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with SHA digest from previous updates
+void HMAC_SHA::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_SHA::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+
+// HMAC_RMD Implementation
+struct HMAC_RMD::HMAC_RMDImpl {
+ TaoCrypt::HMAC<TaoCrypt::RIPEMD160> mac_;
+ HMAC_RMDImpl() {}
+};
+
+
+HMAC_RMD::HMAC_RMD(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_RMDImpl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_RMD::~HMAC_RMD() { delete pimpl_; }
+
+
+uint HMAC_RMD::get_digestSize() const
+{
+ return RMD_LEN;
+}
+
+
+uint HMAC_RMD::get_padSize() const
+{
+ return PAD_RMD;
+}
+
+
+// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz
+void HMAC_RMD::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with RMD digest from previous updates
+void HMAC_RMD::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_RMD::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+struct DES::DESImpl {
+ TaoCrypt::DES_CBC_Encryption encryption;
+ TaoCrypt::DES_CBC_Decryption decryption;
+};
+
+
+DES::DES() : pimpl_(new (ys) DESImpl) {}
+
+DES::~DES() { delete pimpl_; }
+
+
+void DES::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, DES_KEY_SZ, iv);
+}
+
+
+void DES::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, DES_KEY_SZ, iv);
+}
+
+// DES encrypt plain of length sz into cipher
+void DES::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// DES decrypt cipher of length sz into plain
+void DES::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+struct DES_EDE::DES_EDEImpl {
+ TaoCrypt::DES_EDE3_CBC_Encryption encryption;
+ TaoCrypt::DES_EDE3_CBC_Decryption decryption;
+};
+
+
+DES_EDE::DES_EDE() : pimpl_(new (ys) DES_EDEImpl) {}
+
+DES_EDE::~DES_EDE() { delete pimpl_; }
+
+
+void DES_EDE::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, DES_EDE_KEY_SZ, iv);
+}
+
+
+void DES_EDE::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, DES_EDE_KEY_SZ, iv);
+}
+
+
+// 3DES encrypt plain of length sz into cipher
+void DES_EDE::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// 3DES decrypt cipher of length sz into plain
+void DES_EDE::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+// Implementation of alledged RC4
+struct RC4::RC4Impl {
+ TaoCrypt::ARC4::Encryption encryption;
+ TaoCrypt::ARC4::Decryption decryption;
+};
+
+
+RC4::RC4() : pimpl_(new (ys) RC4Impl) {}
+
+RC4::~RC4() { delete pimpl_; }
+
+
+void RC4::set_encryptKey(const byte* k, const byte*)
+{
+ pimpl_->encryption.SetKey(k, RC4_KEY_SZ);
+}
+
+
+void RC4::set_decryptKey(const byte* k, const byte*)
+{
+ pimpl_->decryption.SetKey(k, RC4_KEY_SZ);
+}
+
+
+// RC4 encrypt plain of length sz into cipher
+void RC4::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// RC4 decrypt cipher of length sz into plain
+void RC4::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+
+// Implementation of AES
+struct AES::AESImpl {
+ TaoCrypt::AES_CBC_Encryption encryption;
+ TaoCrypt::AES_CBC_Decryption decryption;
+ unsigned int keySz_;
+
+ AESImpl(unsigned int ks) : keySz_(ks) {}
+};
+
+
+AES::AES(unsigned int ks) : pimpl_(new (ys) AESImpl(ks)) {}
+
+AES::~AES() { delete pimpl_; }
+
+
+int AES::get_keySize() const
+{
+ return pimpl_->keySz_;
+}
+
+
+void AES::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, pimpl_->keySz_, iv);
+}
+
+
+void AES::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, pimpl_->keySz_, iv);
+}
+
+
+// AES encrypt plain of length sz into cipher
+void AES::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// AES decrypt cipher of length sz into plain
+void AES::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+struct RandomPool::RandomImpl {
+ TaoCrypt::RandomNumberGenerator RNG_;
+};
+
+RandomPool::RandomPool() : pimpl_(new (ys) RandomImpl) {}
+
+RandomPool::~RandomPool() { delete pimpl_; }
+
+int RandomPool::GetError() const
+{
+ return pimpl_->RNG_.GetError();
+}
+
+void RandomPool::Fill(opaque* dst, uint sz) const
+{
+ pimpl_->RNG_.GenerateBlock(dst, sz);
+}
+
+
+// Implementation of DSS Authentication
+struct DSS::DSSImpl {
+ void SetPublic (const byte*, unsigned int);
+ void SetPrivate(const byte*, unsigned int);
+ TaoCrypt::DSA_PublicKey publicKey_;
+ TaoCrypt::DSA_PrivateKey privateKey_;
+};
+
+
+// Decode and store the public key
+void DSS::DSSImpl::SetPublic(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ publicKey_.Initialize(source);
+}
+
+
+// Decode and store the public key
+void DSS::DSSImpl::SetPrivate(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ privateKey_.Initialize(source);
+ publicKey_ = TaoCrypt::DSA_PublicKey(privateKey_);
+
+}
+
+
+// Set public or private key
+DSS::DSS(const byte* key, unsigned int sz, bool publicKey)
+ : pimpl_(new (ys) DSSImpl)
+{
+ if (publicKey)
+ pimpl_->SetPublic(key, sz);
+ else
+ pimpl_->SetPrivate(key, sz);
+}
+
+
+DSS::~DSS()
+{
+ delete pimpl_;
+}
+
+
+uint DSS::get_signatureLength() const
+{
+ return pimpl_->publicKey_.SignatureLength();
+}
+
+
+// DSS Sign message of length sz into sig
+void DSS::sign(byte* sig, const byte* sha_digest, unsigned int /* shaSz */,
+ const RandomPool& random)
+{
+ using namespace TaoCrypt;
+
+ DSA_Signer signer(pimpl_->privateKey_);
+ signer.Sign(sha_digest, sig, random.pimpl_->RNG_);
+}
+
+
+// DSS Verify message of length sz against sig, is it correct?
+bool DSS::verify(const byte* sha_digest, unsigned int /* shaSz */,
+ const byte* sig, unsigned int /* sigSz */)
+{
+ using namespace TaoCrypt;
+
+ DSA_Verifier ver(pimpl_->publicKey_);
+ return ver.Verify(sha_digest, sig);
+}
+
+
+// Implementation of RSA key interface
+struct RSA::RSAImpl {
+ void SetPublic (const byte*, unsigned int);
+ void SetPrivate(const byte*, unsigned int);
+ TaoCrypt::RSA_PublicKey publicKey_;
+ TaoCrypt::RSA_PrivateKey privateKey_;
+};
+
+
+// Decode and store the public key
+void RSA::RSAImpl::SetPublic(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ publicKey_.Initialize(source);
+}
+
+
+// Decode and store the private key
+void RSA::RSAImpl::SetPrivate(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ privateKey_.Initialize(source);
+ publicKey_ = TaoCrypt::RSA_PublicKey(privateKey_);
+}
+
+
+// Set public or private key
+RSA::RSA(const byte* key, unsigned int sz, bool publicKey)
+ : pimpl_(new (ys) RSAImpl)
+{
+ if (publicKey)
+ pimpl_->SetPublic(key, sz);
+ else
+ pimpl_->SetPrivate(key, sz);
+}
+
+RSA::~RSA()
+{
+ delete pimpl_;
+}
+
+
+// get cipher text length, varies on key size
+unsigned int RSA::get_cipherLength() const
+{
+ return pimpl_->publicKey_.FixedCiphertextLength();
+}
+
+
+// get signautre length, varies on key size
+unsigned int RSA::get_signatureLength() const
+{
+ return get_cipherLength();
+}
+
+
+// RSA Sign message of length sz into sig
+void RSA::sign(byte* sig, const byte* message, unsigned int sz,
+ const RandomPool& random)
+{
+ TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_);
+ dec.SSL_Sign(message, sz, sig, random.pimpl_->RNG_);
+}
+
+
+// RSA Verify message of length sz against sig
+bool RSA::verify(const byte* message, unsigned int sz, const byte* sig,
+ unsigned int)
+{
+ TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_);
+ return enc.SSL_Verify(message, sz, sig);
+}
+
+
+// RSA public encrypt plain of length sz into cipher
+void RSA::encrypt(byte* cipher, const byte* plain, unsigned int sz,
+ const RandomPool& random)
+{
+
+ TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_);
+ enc.Encrypt(plain, sz, cipher, random.pimpl_->RNG_);
+}
+
+
+// RSA private decrypt cipher of length sz into plain
+void RSA::decrypt(byte* plain, const byte* cipher, unsigned int sz,
+ const RandomPool& random)
+{
+ TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_);
+ dec.Decrypt(cipher, sz, plain, random.pimpl_->RNG_);
+}
+
+
+struct Integer::IntegerImpl {
+ TaoCrypt::Integer int_;
+
+ IntegerImpl() {}
+ explicit IntegerImpl(const TaoCrypt::Integer& i) : int_(i) {}
+};
+
+Integer::Integer() : pimpl_(new (ys) IntegerImpl) {}
+
+Integer::~Integer() { delete pimpl_; }
+
+
+
+Integer::Integer(const Integer& other) : pimpl_(new (ys)
+ IntegerImpl(other.pimpl_->int_))
+{}
+
+
+Integer& Integer::operator=(const Integer& that)
+{
+ pimpl_->int_ = that.pimpl_->int_;
+
+ return *this;
+}
+
+
+void Integer::assign(const byte* num, unsigned int sz)
+{
+ pimpl_->int_ = TaoCrypt::Integer(num, sz);
+}
+
+
+struct DiffieHellman::DHImpl {
+ TaoCrypt::DH dh_;
+ TaoCrypt::RandomNumberGenerator& ranPool_;
+ byte* publicKey_;
+ byte* privateKey_;
+ byte* agreedKey_;
+
+ DHImpl(TaoCrypt::RandomNumberGenerator& r) : ranPool_(r), publicKey_(0),
+ privateKey_(0), agreedKey_(0) {}
+ ~DHImpl() {delete[] agreedKey_; delete[] privateKey_; delete[] publicKey_;}
+
+ DHImpl(const DHImpl& that) : dh_(that.dh_), ranPool_(that.ranPool_),
+ publicKey_(0), privateKey_(0), agreedKey_(0)
+ {
+ uint length = dh_.GetByteLength();
+ AllocKeys(length, length, length);
+ }
+
+ void AllocKeys(unsigned int pubSz, unsigned int privSz, unsigned int agrSz)
+ {
+ publicKey_ = new (ys) byte[pubSz];
+ privateKey_ = new (ys) byte[privSz];
+ agreedKey_ = new (ys) byte[agrSz];
+ }
+};
+
+
+
+/*
+// server Side DH, server's view
+DiffieHellman::DiffieHellman(const char* file, const RandomPool& random)
+ : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using namespace TaoCrypt;
+ Source source;
+ FileSource(file, source);
+ if (source.size() == 0)
+ return; // TODO add error state, and force check
+ HexDecoder hd(source);
+
+ pimpl_->dh_.Initialize(source);
+
+ uint length = pimpl_->dh_.GetByteLength();
+
+ pimpl_->AllocKeys(length, length, length);
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+*/
+
+
+// server Side DH, client's view
+DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g,
+ unsigned int gSz, const byte* pub,
+ unsigned int pubSz, const RandomPool& random)
+ : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using TaoCrypt::Integer;
+
+ pimpl_->dh_.Initialize(Integer(p, pSz).Ref(), Integer(g, gSz).Ref());
+ pimpl_->publicKey_ = new (ys) opaque[pubSz];
+ memcpy(pimpl_->publicKey_, pub, pubSz);
+}
+
+
+// Server Side DH, server's view
+DiffieHellman::DiffieHellman(const Integer& p, const Integer& g,
+ const RandomPool& random)
+: pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using TaoCrypt::Integer;
+
+ pimpl_->dh_.Initialize(p.pimpl_->int_, g.pimpl_->int_);
+
+ uint length = pimpl_->dh_.GetByteLength();
+
+ pimpl_->AllocKeys(length, length, length);
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+
+DiffieHellman::~DiffieHellman() { delete pimpl_; }
+
+
+// Client side and view, use server that for p and g
+DiffieHellman::DiffieHellman(const DiffieHellman& that)
+ : pimpl_(new (ys) DHImpl(*that.pimpl_))
+{
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+
+
+DiffieHellman& DiffieHellman::operator=(const DiffieHellman& that)
+{
+ pimpl_->dh_ = that.pimpl_->dh_;
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+ return *this;
+}
+
+
+void DiffieHellman::makeAgreement(const byte* other)
+{
+ pimpl_->dh_.Agree(pimpl_->agreedKey_, pimpl_->privateKey_, other);
+}
+
+
+uint DiffieHellman::get_agreedKeyLength() const
+{
+ return pimpl_->dh_.GetByteLength();
+}
+
+
+const byte* DiffieHellman::get_agreedKey() const
+{
+ return pimpl_->agreedKey_;
+}
+
+
+const byte* DiffieHellman::get_publicKey() const
+{
+ return pimpl_->publicKey_;
+}
+
+
+void DiffieHellman::set_sizes(int& pSz, int& gSz, int& pubSz) const
+{
+ using TaoCrypt::Integer;
+ Integer p = pimpl_->dh_.GetP();
+ Integer g = pimpl_->dh_.GetG();
+
+ pSz = p.ByteCount();
+ gSz = g.ByteCount();
+ pubSz = pimpl_->dh_.GetByteLength();
+}
+
+
+void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const
+{
+ using TaoCrypt::Integer;
+ Integer p = pimpl_->dh_.GetP();
+ Integer g = pimpl_->dh_.GetG();
+
+ p.Encode(bp, p.ByteCount());
+ g.Encode(bg, g.ByteCount());
+ memcpy(bpub, pimpl_->publicKey_, pimpl_->dh_.GetByteLength());
+}
+
+
+// convert PEM file to DER x509 type
+x509* PemToDer(const char* fname, CertType type)
+{
+ using namespace TaoCrypt;
+
+ char header[80];
+ char footer[80];
+
+ if (type == Cert) {
+ strncpy(header, "-----BEGIN CERTIFICATE-----", sizeof(header));
+ strncpy(footer, "-----END CERTIFICATE-----", sizeof(footer));
+ } else {
+ strncpy(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
+ strncpy(footer, "-----END RSA PRIVATE KEY-----", sizeof(header));
+ }
+
+ FILE* file = fopen(fname, "rb");
+ if (!file)
+ return 0;
+
+ long begin = -1;
+ long end = 0;
+ bool foundEnd = false;
+
+ char line[80];
+
+ while(fgets(line, sizeof(line), file))
+ if (strncmp(header, line, strlen(header)) == 0) {
+ begin = ftell(file);
+ break;
+ }
+
+ while(fgets(line, sizeof(line), file))
+ if (strncmp(footer, line, strlen(footer)) == 0) {
+ foundEnd = true;
+ break;
+ }
+ else
+ end = ftell(file);
+
+ if (begin == -1 || !foundEnd) {
+ fclose(file);
+ return 0;
+ }
+
+ input_buffer tmp(end - begin);
+ fseek(file, begin, SEEK_SET);
+ size_t bytes = fread(tmp.get_buffer(), end - begin, 1, file);
+ if (bytes != 1) {
+ fclose(file);
+ return 0;
+ }
+
+ Source der(tmp.get_buffer(), end - begin);
+ Base64Decoder b64Dec(der);
+
+ uint sz = der.size();
+ mySTL::auto_ptr<x509> x(new (ys) x509(sz));
+ memcpy(x->use_buffer(), der.get_buffer(), sz);
+
+ fclose(file);
+ return x.release();
+}
+
+
+} // namespace
+
+#ifdef __GNUC__
+template class TaoCrypt::HMAC<TaoCrypt::MD5>;
+template class TaoCrypt::HMAC<TaoCrypt::SHA>;
+template class TaoCrypt::HMAC<TaoCrypt::RIPEMD160>;
+template class TaoCrypt::Mode_BASE<16>;
+template class TaoCrypt::Mode_BASE<8>;
+#endif
+
+#endif // !USE_CRYPTOPP_LIB
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
new file mode 100644
index 00000000000..35c4cbd4922
--- /dev/null
+++ b/extra/yassl/src/handshake.cpp
@@ -0,0 +1,1011 @@
+/* handshake.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The handshake source implements functions for creating and reading
+ * the various handshake messages.
+ */
+
+#include "runtime.hpp"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+// Build a client hello message from cipher suites and compression method
+void buildClientHello(SSL& ssl, ClientHello& hello,
+ CompressionMethod compression = no_compression)
+{
+ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
+ if (ssl.getSecurity().get_resuming()) {
+ hello.id_len_ = ID_LEN;
+ memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN);
+ }
+ else
+ hello.id_len_ = 0;
+ hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_;
+ memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_,
+ hello.suite_len_);
+ hello.comp_len_ = 1;
+ hello.compression_methods_ = compression;
+
+ hello.set_length(sizeof(ProtocolVersion) +
+ RAN_LEN +
+ hello.id_len_ + sizeof(hello.id_len_) +
+ hello.suite_len_ + sizeof(hello.suite_len_) +
+ hello.comp_len_ + sizeof(hello.comp_len_));
+}
+
+
+// Build a server hello message
+void buildServerHello(SSL& ssl, ServerHello& hello)
+{
+ if (ssl.getSecurity().get_resuming()) {
+ memcpy(hello.random_,ssl.getSecurity().get_connection().server_random_,
+ RAN_LEN);
+ memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN);
+ }
+ else {
+ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
+ ssl.getCrypto().get_random().Fill(hello.session_id_, ID_LEN);
+ }
+ hello.id_len_ = ID_LEN;
+ ssl.set_sessionID(hello.session_id_);
+
+ hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0];
+ hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1];
+ hello.compression_method_ = no_compression;
+
+ hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN +
+ sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM);
+}
+
+
+// add handshake from buffer into md5 and sha hashes, use handshake header
+void hashHandShake(SSL& ssl, const input_buffer& input, uint sz)
+{
+ const opaque* buffer = input.get_buffer() + input.get_current() -
+ HANDSHAKE_HEADER;
+ sz += HANDSHAKE_HEADER;
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+}
+
+
+// locals
+namespace {
+
+// Write a plaintext record to buffer
+void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
+ const Message& msg)
+{
+ buffer.allocate(RECORD_HEADER + rlHdr.length_);
+ buffer << rlHdr << msg;
+}
+
+
+// Write a plaintext record to buffer
+void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
+ const HandShakeHeader& hsHdr, const HandShakeBase& shake)
+{
+ buffer.allocate(RECORD_HEADER + rlHdr.length_);
+ buffer << rlHdr << hsHdr << shake;
+}
+
+
+// Build Record Layer header for Message without handshake header
+void buildHeader(SSL& ssl, RecordLayerHeader& rlHeader, const Message& msg)
+{
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ rlHeader.type_ = msg.get_type();
+ rlHeader.version_.major_ = pv.major_;
+ rlHeader.version_.minor_ = pv.minor_;
+ rlHeader.length_ = msg.get_length();
+}
+
+
+// Build HandShake and RecordLayer Headers for handshake output
+void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader,
+ RecordLayerHeader& rlHeader, const HandShakeBase& shake)
+{
+ int sz = shake.get_length();
+
+ hsHeader.set_type(shake.get_type());
+ hsHeader.set_length(sz);
+
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ rlHeader.type_ = handshake;
+ rlHeader.version_.major_ = pv.major_;
+ rlHeader.version_.minor_ = pv.minor_;
+ rlHeader.length_ = sz + HANDSHAKE_HEADER;
+}
+
+
+// add handshake from buffer into md5 and sha hashes, exclude record header
+void hashHandShake(SSL& ssl, const output_buffer& output)
+{
+ uint sz = output.get_size() - RECORD_HEADER;
+
+ const opaque* buffer = output.get_buffer() + RECORD_HEADER;
+
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+}
+
+
+// calculate MD5 hash for finished
+void buildMD5(SSL& ssl, Finished& fin, const opaque* sender)
+{
+
+ opaque md5_result[MD5_LEN];
+ opaque md5_inner[SIZEOF_SENDER + SECRET_LEN + PAD_MD5];
+ opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make md5 inner
+ memcpy(md5_inner, sender, SIZEOF_SENDER);
+ memcpy(&md5_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
+ memcpy(&md5_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_MD5);
+
+ ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
+ sizeof(md5_inner));
+
+ // make md5 outer
+ memcpy(md5_outer, master_secret, SECRET_LEN);
+ memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
+ memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
+
+ ssl.useHashes().use_MD5().get_digest(fin.set_md5(), md5_outer,
+ sizeof(md5_outer));
+}
+
+
+// calculate SHA hash for finished
+void buildSHA(SSL& ssl, Finished& fin, const opaque* sender)
+{
+
+ opaque sha_result[SHA_LEN];
+ opaque sha_inner[SIZEOF_SENDER + SECRET_LEN + PAD_SHA];
+ opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make sha inner
+ memcpy(sha_inner, sender, SIZEOF_SENDER);
+ memcpy(&sha_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
+ memcpy(&sha_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_SHA);
+
+ ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
+ sizeof(sha_inner));
+
+ // make sha outer
+ memcpy(sha_outer, master_secret, SECRET_LEN);
+ memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
+ memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
+
+ ssl.useHashes().use_SHA().get_digest(fin.set_sha(), sha_outer,
+ sizeof(sha_outer));
+}
+
+
+// decrypt input message in place, store size in case needed later
+void decrypt_message(SSL& ssl, input_buffer& input, uint sz)
+{
+ input_buffer plain(sz);
+ opaque* cipher = input.get_buffer() + input.get_current();
+
+ ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz);
+ memcpy(cipher, plain.get_buffer(), sz);
+ ssl.useSecurity().use_parms().encrypt_size_ = sz;
+}
+
+
+// write headers, handshake hash, mac, pad, and encrypt
+void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output)
+{
+ uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
+ uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz;
+ uint pad = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ sz += 1; // pad byte
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ pad = (sz - RECORD_HEADER) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ buildHeaders(ssl, hsHeader, rlHeader, fin);
+ rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
+ // and pad, hanshake doesn't
+ output.allocate(sz);
+ output << rlHeader << hsHeader << fin;
+
+ hashHandShake(ssl, output);
+ opaque digest[SHA_LEN]; // max size
+ if (ssl.isTLS())
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, handshake);
+ else
+ hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, handshake);
+ output.write(digest, digestSz);
+
+ if (ssl.getSecurity().get_parms().cipher_type_ == block)
+ for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
+ // pad value too
+ input_buffer cipher(rlHeader.length_);
+ ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
+ output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
+ output.set_current(RECORD_HEADER);
+ output.write(cipher.get_buffer(), cipher.get_capacity());
+}
+
+
+// build an encrypted data or alert message for output
+void buildMessage(SSL& ssl, output_buffer& output, const Message& msg)
+{
+ uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ uint sz = RECORD_HEADER + msg.get_length() + digestSz;
+ uint pad = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ sz += 1; // pad byte
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ pad = (sz - RECORD_HEADER) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, msg);
+ rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
+ // and pad, hanshake doesn't
+ output.allocate(sz);
+ output << rlHeader << msg;
+
+ opaque digest[SHA_LEN]; // max size
+ if (ssl.isTLS())
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, msg.get_type());
+ else
+ hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, msg.get_type());
+ output.write(digest, digestSz);
+
+ if (ssl.getSecurity().get_parms().cipher_type_ == block)
+ for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
+ // pad value too
+ input_buffer cipher(rlHeader.length_);
+ ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
+ output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
+ output.set_current(RECORD_HEADER);
+ output.write(cipher.get_buffer(), cipher.get_capacity());
+}
+
+
+// build alert message
+void buildAlert(SSL& ssl, output_buffer& output, const Alert& alert)
+{
+ if (ssl.getSecurity().get_parms().pending_ == false) // encrypted
+ buildMessage(ssl, output, alert);
+ else {
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, alert);
+ buildOutput(output, rlHeader, alert);
+ }
+}
+
+
+// build TLS finished message
+void buildFinishedTLS(SSL& ssl, Finished& fin, const opaque* sender)
+{
+ opaque handshake_hash[FINISHED_SZ];
+
+ ssl.useHashes().use_MD5().get_digest(handshake_hash);
+ ssl.useHashes().use_SHA().get_digest(&handshake_hash[MD5_LEN]);
+
+ const opaque* side;
+ if ( strncmp((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
+ side = tls_client;
+ else
+ side = tls_server;
+
+ PRF(fin.set_md5(), TLS_FINISHED_SZ,
+ ssl.getSecurity().get_connection().master_secret_, SECRET_LEN,
+ side, FINISHED_LABEL_SZ,
+ handshake_hash, FINISHED_SZ);
+
+ fin.set_length(TLS_FINISHED_SZ); // shorter length for TLS
+}
+
+
+// compute p_hash for MD5 or SHA-1 for TLSv1 PRF
+void p_hash(output_buffer& result, const output_buffer& secret,
+ const output_buffer& seed, MACAlgorithm hash)
+{
+ uint len = hash == md5 ? MD5_LEN : SHA_LEN;
+ uint times = result.get_capacity() / len;
+ uint lastLen = result.get_capacity() % len;
+ opaque previous[SHA_LEN]; // max size
+ opaque current[SHA_LEN]; // max size
+ mySTL::auto_ptr<Digest> hmac;
+
+ if (lastLen) times += 1;
+
+ if (hash == md5)
+ hmac.reset(new (ys) HMAC_MD5(secret.get_buffer(), secret.get_size()));
+ else
+ hmac.reset(new (ys) HMAC_SHA(secret.get_buffer(), secret.get_size()));
+ // A0 = seed
+ hmac->get_digest(previous, seed.get_buffer(), seed.get_size());// A1
+ uint lastTime = times - 1;
+
+ for (uint i = 0; i < times; i++) {
+ hmac->update(previous, len);
+ hmac->get_digest(current, seed.get_buffer(), seed.get_size());
+
+ if (lastLen && (i == lastTime))
+ result.write(current, lastLen);
+ else {
+ result.write(current, len);
+ //memcpy(previous, current, len);
+ hmac->get_digest(previous, previous, len);
+ }
+ }
+}
+
+
+// calculate XOR for TLSv1 PRF
+void get_xor(byte *digest, uint digLen, output_buffer& md5,
+ output_buffer& sha)
+{
+ for (uint i = 0; i < digLen; i++)
+ digest[i] = md5[AUTO] ^ sha[AUTO];
+}
+
+
+// build MD5 part of certificate verify
+void buildMD5_CertVerify(SSL& ssl, byte* digest)
+{
+ opaque md5_result[MD5_LEN];
+ opaque md5_inner[SECRET_LEN + PAD_MD5];
+ opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make md5 inner
+ memcpy(md5_inner, master_secret, SECRET_LEN);
+ memcpy(&md5_inner[SECRET_LEN], PAD1, PAD_MD5);
+
+ ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
+ sizeof(md5_inner));
+
+ // make md5 outer
+ memcpy(md5_outer, master_secret, SECRET_LEN);
+ memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
+ memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
+
+ ssl.useHashes().use_MD5().get_digest(digest, md5_outer, sizeof(md5_outer));
+}
+
+
+// build SHA part of certificate verify
+void buildSHA_CertVerify(SSL& ssl, byte* digest)
+{
+ opaque sha_result[SHA_LEN];
+ opaque sha_inner[SECRET_LEN + PAD_SHA];
+ opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make sha inner
+ memcpy(sha_inner, master_secret, SECRET_LEN);
+ memcpy(&sha_inner[SECRET_LEN], PAD1, PAD_SHA);
+
+ ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
+ sizeof(sha_inner));
+
+ // make sha outer
+ memcpy(sha_outer, master_secret, SECRET_LEN);
+ memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
+ memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
+
+ ssl.useHashes().use_SHA().get_digest(digest, sha_outer, sizeof(sha_outer));
+}
+
+
+} // namespace for locals
+
+
+// some clients still send sslv2 client hello
+void ProcessOldClientHello(input_buffer& input, SSL& ssl)
+{
+ byte b0 = input[AUTO];
+ byte b1 = input[AUTO];
+
+ uint16 sz = ((b0 & 0x7f) << 8) | b1;
+
+ // hashHandShake manually
+ const opaque* buffer = input.get_buffer() + input.get_current();
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+
+ b1 = input[AUTO]; // does this value mean client_hello?
+
+ ClientHello ch;
+ ch.client_version_.major_ = input[AUTO];
+ ch.client_version_.minor_ = input[AUTO];
+
+ byte len[2];
+
+ input.read(len, sizeof(len));
+ ato16(len, ch.suite_len_);
+
+ input.read(len, sizeof(len));
+ uint16 sessionLen;
+ ato16(len, sessionLen);
+ ch.id_len_ = sessionLen;
+
+ input.read(len, sizeof(len));
+ uint16 randomLen;
+ ato16(len, randomLen);
+
+ int j = 0;
+ for (uint16 i = 0; i < ch.suite_len_; i += 3) {
+ byte first = input[AUTO];
+ if (first) // sslv2 type
+ input.read(len, SUITE_LEN); // skip
+ else {
+ input.read(&ch.cipher_suites_[j], SUITE_LEN);
+ j += SUITE_LEN;
+ }
+ }
+ ch.suite_len_ = j;
+
+ if (ch.id_len_)
+ input.read(ch.session_id_, ch.id_len_);
+
+ if (randomLen < RAN_LEN)
+ memset(ch.random_, 0, RAN_LEN - randomLen);
+ input.read(&ch.random_[RAN_LEN - randomLen], randomLen);
+
+
+ ch.Process(input, ssl);
+}
+
+
+// Build a finished message, see 7.6.9
+void buildFinished(SSL& ssl, Finished& fin, const opaque* sender)
+{
+ // store current states, building requires get_digest which resets state
+ MD5 md5(ssl.getHashes().get_MD5());
+ SHA sha(ssl.getHashes().get_SHA());
+
+ if (ssl.isTLS())
+ buildFinishedTLS(ssl, fin, sender);
+ else {
+ buildMD5(ssl, fin, sender);
+ buildSHA(ssl, fin, sender);
+ }
+
+ // restore
+ ssl.useHashes().use_MD5() = md5;
+ ssl.useHashes().use_SHA() = sha;
+}
+
+
+/* compute SSLv3 HMAC into digest see
+ * buffer is of sz size and includes HandShake Header but not a Record Header
+ * verify means to check peers hmac
+*/
+void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
+ ContentType content, bool verify)
+{
+ Digest& mac = ssl.useCrypto().use_digest();
+ opaque inner[SHA_LEN + PAD_MD5 + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ];
+ opaque outer[SHA_LEN + PAD_MD5 + SHA_LEN];
+ opaque result[SHA_LEN]; // max possible sizes
+ uint digestSz = mac.get_digestSize(); // actual sizes
+ uint padSz = mac.get_padSize();
+ uint innerSz = digestSz + padSz + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ;
+ uint outerSz = digestSz + padSz + digestSz;
+
+ // data
+ const opaque* mac_secret = ssl.get_macSecret(verify);
+ opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ opaque length[LENGTH_SZ];
+ c16toa(sz, length);
+ c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
+
+ // make inner
+ memcpy(inner, mac_secret, digestSz);
+ memcpy(&inner[digestSz], PAD1, padSz);
+ memcpy(&inner[digestSz + padSz], seq, SEQ_SZ);
+ inner[digestSz + padSz + SEQ_SZ] = content;
+ memcpy(&inner[digestSz + padSz + SEQ_SZ + SIZEOF_ENUM], length, LENGTH_SZ);
+
+ mac.update(inner, innerSz);
+ mac.get_digest(result, buffer, sz); // append content buffer
+
+ // make outer
+ memcpy(outer, mac_secret, digestSz);
+ memcpy(&outer[digestSz], PAD2, padSz);
+ memcpy(&outer[digestSz + padSz], result, digestSz);
+
+ mac.get_digest(digest, outer, outerSz);
+}
+
+
+// TLS type HAMC
+void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
+ ContentType content, bool verify)
+{
+ mySTL::auto_ptr<Digest> hmac;
+ opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ opaque length[LENGTH_SZ];
+ opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len
+
+ c16toa(sz, length);
+ c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
+
+ MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_;
+
+ if (algo == sha)
+ hmac.reset(new (ys) HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN));
+ else if (algo == rmd)
+ hmac.reset(new (ys) HMAC_RMD(ssl.get_macSecret(verify), RMD_LEN));
+ else
+ hmac.reset(new (ys) HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN));
+
+ hmac->update(seq, SEQ_SZ); // seq_num
+ inner[0] = content; // type
+ inner[SIZEOF_ENUM] = ssl.getSecurity().get_connection().version_.major_;
+ inner[SIZEOF_ENUM + SIZEOF_ENUM] =
+ ssl.getSecurity().get_connection().version_.minor_; // version
+ memcpy(&inner[SIZEOF_ENUM + VERSION_SZ], length, LENGTH_SZ); // length
+ hmac->update(inner, sizeof(inner));
+ hmac->get_digest(digest, buffer, sz); // content
+}
+
+
+// compute TLSv1 PRF (pseudo random function using HMAC)
+void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
+ const byte* label, uint labLen, const byte* seed, uint seedLen)
+{
+ uint half = secLen / 2 + secLen % 2;
+
+ output_buffer md5_half(half);
+ output_buffer sha_half(half);
+ output_buffer labelSeed(labLen + seedLen);
+
+ md5_half.write(secret, half);
+ sha_half.write(secret + half - secLen % 2, half);
+ labelSeed.write(label, labLen);
+ labelSeed.write(seed, seedLen);
+
+ output_buffer md5_result(digLen);
+ output_buffer sha_result(digLen);
+
+ p_hash(md5_result, md5_half, labelSeed, md5);
+ p_hash(sha_result, sha_half, labelSeed, sha);
+
+ md5_result.set_current(0);
+ sha_result.set_current(0);
+ get_xor(digest, digLen, md5_result, sha_result);
+}
+
+
+// build certificate hashes
+void build_certHashes(SSL& ssl, Hashes& hashes)
+{
+ // store current states, building requires get_digest which resets state
+ MD5 md5(ssl.getHashes().get_MD5());
+ SHA sha(ssl.getHashes().get_SHA());
+
+ if (ssl.isTLS()) {
+ ssl.useHashes().use_MD5().get_digest(hashes.md5_);
+ ssl.useHashes().use_SHA().get_digest(hashes.sha_);
+ }
+ else {
+ buildMD5_CertVerify(ssl, hashes.md5_);
+ buildSHA_CertVerify(ssl, hashes.sha_);
+ }
+
+ // restore
+ ssl.useHashes().use_MD5() = md5;
+ ssl.useHashes().use_SHA() = sha;
+}
+
+
+mySTL::auto_ptr<input_buffer> null_buffer;
+
+// do process input requests
+mySTL::auto_ptr<input_buffer>
+DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
+{
+ ssl.getSocket().wait(); // wait for input if blocking
+ uint ready = ssl.getSocket().get_ready();
+ if (!ready) return buffered;
+
+ // add buffered data if its there
+ uint buffSz = buffered.get() ? buffered.get()->get_size() : 0;
+ input_buffer buffer(buffSz + ready);
+ if (buffSz) {
+ buffer.assign(buffered.get()->get_buffer(), buffSz);
+ buffered = null_buffer;
+ }
+
+ // add new data
+ uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready);
+ buffer.add_size(read);
+ uint offset = 0;
+ const MessageFactory& mf = ssl.getFactory().getMessage();
+
+ // old style sslv2 client hello?
+ if (ssl.getSecurity().get_parms().entity_ == server_end &&
+ ssl.getStates().getServer() == clientNull)
+ if (buffer.peek() != handshake)
+ ProcessOldClientHello(buffer, ssl);
+
+ while(!buffer.eof()) {
+ // each record
+ RecordLayerHeader hdr;
+ buffer >> hdr;
+ ssl.verifyState(hdr);
+
+ // make sure we have enough input in buffer to process this record
+ if (hdr.length_ > buffer.get_remaining()) {
+ uint sz = buffer.get_remaining() + RECORD_HEADER;
+ buffered.reset(new (ys) input_buffer(sz, buffer.get_buffer() +
+ buffer.get_current() - RECORD_HEADER, sz));
+ break;
+ }
+
+ while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) {
+ // each message in record
+ if (ssl.getSecurity().get_parms().pending_ == false) // cipher on
+ decrypt_message(ssl, buffer, hdr.length_);
+ mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_));
+ if (!msg.get()) {
+ ssl.SetError(factory_error);
+ return buffered = null_buffer;
+ }
+ buffer >> *msg;
+ msg->Process(buffer, ssl);
+ if (ssl.GetError()) return buffered = null_buffer;
+ }
+ offset += hdr.length_ + RECORD_HEADER;
+ }
+ return buffered; // done, don't call again
+}
+
+
+// process input requests
+void processReply(SSL& ssl)
+{
+ if (ssl.GetError()) return;
+ mySTL::auto_ptr<input_buffer> buffered;
+
+ for (;;) {
+ mySTL::auto_ptr<input_buffer> tmp = DoProcessReply(ssl, buffered);
+ if (tmp.get()) // had only part of a record's data, call again
+ buffered = tmp;
+ else
+ break;
+ }
+}
+
+
+// send client_hello, no buffering
+void sendClientHello(SSL& ssl)
+{
+ ssl.verifyState(serverNull);
+ if (ssl.GetError()) return;
+
+ ClientHello ch(ssl.getSecurity().get_connection().version_);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ output_buffer out;
+
+ buildClientHello(ssl, ch);
+ ssl.set_random(ch.get_random(), client_end);
+ buildHeaders(ssl, hsHeader, rlHeader, ch);
+ buildOutput(out, rlHeader, hsHeader, ch);
+ hashHandShake(ssl, out);
+
+ ssl.Send(out.get_buffer(), out.get_size());
+}
+
+
+// send client key exchange
+void sendClientKeyExchange(SSL& ssl, BufferOutput buffer)
+{
+ ssl.verifyState(serverHelloDoneComplete);
+ if (ssl.GetError()) return;
+
+ ClientKeyExchange ck(ssl);
+ ck.build(ssl);
+ ssl.makeMasterSecret();
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ buildHeaders(ssl, hsHeader, rlHeader, ck);
+ buildOutput(*out.get(), rlHeader, hsHeader, ck);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send server key exchange
+void sendServerKeyExchange(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+ ServerKeyExchange sk(ssl);
+ sk.build(ssl);
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ buildHeaders(ssl, hsHeader, rlHeader, sk);
+ buildOutput(*out.get(), rlHeader, hsHeader, sk);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send change cipher
+void sendChangeCipher(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.getSecurity().get_parms().entity_ == server_end)
+ if (ssl.getSecurity().get_resuming())
+ ssl.verifyState(clientKeyExchangeComplete);
+ else
+ ssl.verifyState(clientFinishedComplete);
+ if (ssl.GetError()) return;
+
+ ChangeCipherSpec ccs;
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, ccs);
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ buildOutput(*out.get(), rlHeader, ccs);
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send finished
+void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ Finished fin;
+ buildFinished(ssl, fin, side == client_end ? client : server);
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ cipherFinished(ssl, fin, *out.get()); // hashes handshake
+
+ if (ssl.getSecurity().get_resuming()) {
+ if (side == server_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
+ }
+ else {
+ GetSessions().add(ssl); // store session
+ if (side == client_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
+ }
+ ssl.useSecurity().use_connection().CleanMaster();
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send data
+int sendData(SSL& ssl, const void* buffer, int sz)
+{
+ ssl.verfiyHandShakeComplete();
+ if (ssl.GetError()) return 0;
+ int sent = 0;
+
+ for (;;) {
+ int len = min(sz - sent, MAX_RECORD_SIZE);
+ output_buffer out;
+ const Data data(len, static_cast<const opaque*>(buffer) + sent);
+
+ buildMessage(ssl, out, data);
+ ssl.Send(out.get_buffer(), out.get_size());
+
+ if (ssl.GetError()) return 0;
+ sent += len;
+ if (sent == sz) break;
+ }
+ ssl.useLog().ShowData(sent, true);
+ return sent;
+}
+
+
+// send alert
+int sendAlert(SSL& ssl, const Alert& alert)
+{
+ output_buffer out;
+ buildAlert(ssl, out, alert);
+ ssl.Send(out.get_buffer(), out.get_size());
+
+ return alert.get_length();
+}
+
+
+// process input data
+int receiveData(SSL& ssl, Data& data)
+{
+ ssl.verfiyHandShakeComplete();
+ if (ssl.GetError()) return 0;
+
+ if (!ssl.bufferedData())
+ processReply(ssl);
+ ssl.fillData(data);
+ ssl.useLog().ShowData(data.get_length());
+
+ if (ssl.GetError()) return 0;
+ return data.get_length();
+}
+
+
+// send server hello
+void sendServerHello(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.getSecurity().get_resuming())
+ ssl.verifyState(clientKeyExchangeComplete);
+ else
+ ssl.verifyState(clientHelloComplete);
+ if (ssl.GetError()) return;
+
+ ServerHello sh(ssl.getSecurity().get_connection().version_);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildServerHello(ssl, sh);
+ ssl.set_random(sh.get_random(), server_end);
+ buildHeaders(ssl, hsHeader, rlHeader, sh);
+ buildOutput(*out.get(), rlHeader, hsHeader, sh);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send server hello done
+void sendServerHelloDone(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ ServerHelloDone shd;
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, shd);
+ buildOutput(*out.get(), rlHeader, hsHeader, shd);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate
+void sendCertificate(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ Certificate cert(ssl.getCrypto().get_certManager().get_cert());
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, cert);
+ buildOutput(*out.get(), rlHeader, hsHeader, cert);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate request
+void sendCertificateRequest(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ CertificateRequest request;
+ request.Build();
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, request);
+ buildOutput(*out.get(), rlHeader, hsHeader, request);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate verify
+void sendCertificateVerify(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ CertificateVerify verify;
+ verify.Build(ssl);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, verify);
+ buildOutput(*out.get(), rlHeader, hsHeader, verify);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp
new file mode 100644
index 00000000000..221ec0cdb4f
--- /dev/null
+++ b/extra/yassl/src/lock.cpp
@@ -0,0 +1,90 @@
+/* lock.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Locking functions
+ */
+
+#include "runtime.hpp"
+#include "lock.hpp"
+
+
+namespace yaSSL {
+
+
+#ifdef MULTI_THREADED
+ #ifdef WIN32
+
+ Mutex::Mutex()
+ {
+ InitializeCriticalSection(&cs_);
+ }
+
+
+ Mutex::~Mutex()
+ {
+ DeleteCriticalSection(&cs_);
+ }
+
+
+ Mutex::Lock::Lock(Mutex& lm) : mutex_(lm)
+ {
+ EnterCriticalSection(&mutex_.cs_);
+ }
+
+
+ Mutex::Lock::~Lock()
+ {
+ LeaveCriticalSection(&mutex_.cs_);
+ }
+
+ #else // WIN32
+
+ Mutex::Mutex()
+ {
+ pthread_mutex_init(&mutex_, 0);
+ }
+
+
+ Mutex::~Mutex()
+ {
+ pthread_mutex_destroy(&mutex_);
+ }
+
+
+ Mutex::Lock::Lock(Mutex& lm) : mutex_(lm)
+ {
+ pthread_mutex_lock(&mutex_.mutex_);
+ }
+
+
+ Mutex::Lock::~Lock()
+ {
+ pthread_mutex_unlock(&mutex_.mutex_);
+ }
+
+
+ #endif // WIN32
+#endif // MULTI_THREADED
+
+
+
+} // namespace yaSSL
+
diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp
new file mode 100644
index 00000000000..eb4776d3d19
--- /dev/null
+++ b/extra/yassl/src/log.cpp
@@ -0,0 +1,148 @@
+/* log.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Debug logging functions
+ */
+
+#include "runtime.hpp"
+#include "log.hpp"
+
+#ifdef YASSL_LOG
+ #include <ctime>
+ #include <cstdio>
+ #include <cstring>
+#endif
+
+
+
+namespace yaSSL {
+
+
+#ifdef YASSL_LOG
+
+ enum { MAX_MSG = 81 };
+
+ Log::Log(const char* str)
+ {
+ log_ = fopen(str, "w");
+ Trace("********** Logger Attached **********");
+ }
+
+
+ Log::~Log()
+ {
+ Trace("********** Logger Detached **********");
+ fclose(log_);
+ }
+
+
+ // Trace a message
+ void Log::Trace(const char* str)
+ {
+ if (!log_) return;
+
+ time_t clicks = time(0);
+ char timeStr[32];
+
+ // get rid of newline
+ strncpy(timeStr, ctime(&clicks), sizeof(timeStr));
+ unsigned int len = strlen(timeStr);
+ timeStr[len - 1] = 0;
+
+ char msg[MAX_MSG];
+
+ strncpy(msg, timeStr, sizeof(timeStr));
+ strncat(msg, ":", 1);
+ strncat(msg, str, MAX_MSG - sizeof(timeStr) - 2);
+ strncat(msg, "\n", 1);
+ msg[MAX_MSG - 1] = 0;
+
+ fputs(msg, log_);
+ }
+
+
+ #if defined(WIN32) || defined(__MACH__) || defined(__hpux__)
+ typedef int socklen_t;
+ #endif
+
+
+ // write tcp address
+ void Log::ShowTCP(socket_t fd, bool ended)
+ {
+ sockaddr_in peeraddr;
+ socklen_t len = sizeof(peeraddr);
+ if (getpeername(fd, (sockaddr*)&peeraddr, &len) != 0)
+ return;
+
+ const char* p = reinterpret_cast<const char*>(&peeraddr.sin_addr);
+ char msg[MAX_MSG];
+ char number[16];
+
+ if (ended)
+ strncpy(msg, "yaSSL conn DONE w/ peer ", 26);
+ else
+ strncpy(msg, "yaSSL conn BEGUN w/ peer ", 26);
+ for (int i = 0; i < 4; ++i) {
+ sprintf(number, "%u", static_cast<unsigned short>(p[i]));
+ strncat(msg, number, 8);
+ if (i < 3)
+ strncat(msg, ".", 1);
+ }
+ strncat(msg, " port ", 8);
+ sprintf(number, "%d", htons(peeraddr.sin_port));
+ strncat(msg, number, 8);
+
+ msg[MAX_MSG - 1] = 0;
+ Trace(msg);
+ }
+
+
+ // log processed data
+ void Log::ShowData(uint bytes, bool sent)
+ {
+ char msg[MAX_MSG];
+ char number[16];
+
+ if (sent)
+ strncpy(msg, "Sent ", 10);
+ else
+ strncpy(msg, "Received ", 10);
+ sprintf(number, "%u", bytes);
+ strncat(msg, number, 8);
+ strncat(msg, " bytes of application data", 27);
+
+ msg[MAX_MSG - 1] = 0;
+ Trace(msg);
+ }
+
+
+#else // no YASSL_LOG
+
+
+ Log::Log(const char*) {}
+ Log::~Log() {}
+ void Log::Trace(const char*) {}
+ void Log::ShowTCP(socket_t, bool) {}
+ void Log::ShowData(uint, bool) {}
+
+
+#endif // YASSL_LOG
+} // namespace
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
new file mode 100644
index 00000000000..0dd30e6b696
--- /dev/null
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -0,0 +1,168 @@
+/* socket_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The socket wrapper source implements a Socket class that hides the
+ * differences between Berkely style sockets and Windows sockets, allowing
+ * transparent TCP access.
+ */
+
+
+#include "runtime.hpp"
+#include "socket_wrapper.hpp"
+#include "yassl_error.hpp"
+
+#ifndef WIN32
+ #include <errno.h>
+ #include <netdb.h>
+ #include <unistd.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ #include <sys/ioctl.h>
+ #include <string.h>
+#endif // WIN32
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#ifdef WIN32
+ const int SOCKET_EINVAL = WSAEINVAL;
+ const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
+#else
+ const int SOCKET_EINVAL = EINVAL;
+ const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
+#endif // WIN32
+
+
+namespace yaSSL {
+
+
+Socket::Socket(socket_t s)
+ : socket_(s)
+{}
+
+
+void Socket::set_fd(socket_t s)
+{
+ socket_ = s;
+}
+
+
+socket_t Socket::get_fd() const
+{
+ return socket_;
+}
+
+
+Socket::~Socket()
+{
+ closeSocket();
+}
+
+
+void Socket::closeSocket()
+{
+ if (socket_ != INVALID_SOCKET) {
+#ifdef WIN32
+ closesocket(socket_);
+#else
+ close(socket_);
+#endif
+ socket_ = INVALID_SOCKET;
+ }
+}
+
+
+uint Socket::get_ready() const
+{
+ unsigned long ready = 0;
+
+#ifdef WIN32
+ ioctlsocket(socket_, FIONREAD, &ready);
+#else
+ ioctl(socket_, FIONREAD, &ready);
+#endif
+
+ return ready;
+}
+
+
+uint Socket::send(const byte* buf, unsigned int sz, int flags) const
+{
+ assert(socket_ != INVALID_SOCKET);
+ int sent = ::send(socket_, reinterpret_cast<const char *>(buf), sz, flags);
+
+ if (sent == -1)
+ return 0;
+
+ return sent;
+}
+
+
+uint Socket::receive(byte* buf, unsigned int sz, int flags) const
+{
+ assert(socket_ != INVALID_SOCKET);
+ int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
+
+ if (recvd == -1)
+ return 0;
+
+ return recvd;
+}
+
+
+// wait if blocking for input, or error
+void Socket::wait() const
+{
+ byte b;
+ receive(&b, 1, MSG_PEEK);
+}
+
+
+void Socket::shutDown(int how)
+{
+ assert(socket_ != INVALID_SOCKET);
+ shutdown(socket_, how);
+}
+
+
+int Socket::get_lastError()
+{
+#ifdef WIN32
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+
+void Socket::set_lastError(int errorCode)
+{
+#ifdef WIN32
+ WSASetLastError(errorCode);
+#else
+ errno = errorCode;
+#endif
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
new file mode 100644
index 00000000000..065b3c260bf
--- /dev/null
+++ b/extra/yassl/src/ssl.cpp
@@ -0,0 +1,1039 @@
+/* ssl.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* SSL source implements all openssl compatibility API functions
+ *
+ * TODO: notes are mostly api additions to allow compilation with mysql
+ * they don't affect normal modes but should be provided for completeness
+
+ * stunnel functions at end of file
+ */
+
+
+
+
+/* see man pages for function descriptions */
+
+#include "runtime.hpp"
+#include "openssl/ssl.h"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+#include <cstdio>
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+SSL_METHOD* SSLv3_method()
+{
+ return SSLv3_client_method();
+}
+
+
+SSL_METHOD* SSLv3_server_method()
+{
+ return new SSL_METHOD(server_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* SSLv3_client_method()
+{
+ return new SSL_METHOD(client_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* TLSv1_server_method()
+{
+ return new SSL_METHOD(server_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* TLSv1_client_method()
+{
+ return new SSL_METHOD(client_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* SSLv23_server_method()
+{
+ // compatibility only, no version 2 support
+ return SSLv3_server_method();
+}
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
+{
+ return new SSL_CTX(method);
+}
+
+
+void SSL_CTX_free(SSL_CTX* ctx)
+{
+ delete ctx;
+}
+
+
+SSL* SSL_new(SSL_CTX* ctx)
+{
+ return new SSL(ctx);
+}
+
+
+void SSL_free(SSL* ssl)
+{
+ delete ssl;
+}
+
+
+int SSL_set_fd(SSL* ssl, int fd)
+{
+ ssl->useSocket().set_fd(fd);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_connect(SSL* ssl)
+{
+ sendClientHello(*ssl);
+ processReply(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificate(*ssl);
+
+ if (!ssl->getSecurity().get_resuming())
+ sendClientKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificateVerify(*ssl);
+
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, client_end);
+ ssl->flushBuffer();
+ if (!ssl->getSecurity().get_resuming())
+ processReply(*ssl);
+
+ ssl->verifyState(serverFinishedComplete);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError())
+ return SSL_FATAL_ERROR;
+ return SSL_SUCCESS;
+}
+
+
+int SSL_write(SSL* ssl, const void* buffer, int sz)
+{
+ return sendData(*ssl, buffer, sz);
+}
+
+
+int SSL_read(SSL* ssl, void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*ssl, data);
+}
+
+
+int SSL_accept(SSL* ssl)
+{
+ processReply(*ssl);
+ sendServerHello(*ssl);
+
+ if (!ssl->getSecurity().get_resuming()) {
+ sendCertificate(*ssl);
+
+ if (ssl->getSecurity().get_connection().send_server_key_)
+ sendServerKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().verifyPeer())
+ sendCertificateRequest(*ssl);
+
+ sendServerHelloDone(*ssl);
+ ssl->flushBuffer();
+
+ processReply(*ssl);
+ }
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, server_end);
+ ssl->flushBuffer();
+ if (ssl->getSecurity().get_resuming())
+ processReply(*ssl);
+
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError())
+ return SSL_FATAL_ERROR;
+ return SSL_SUCCESS;
+}
+
+
+int SSL_do_handshake(SSL* ssl)
+{
+ if (ssl->getSecurity().get_parms().entity_ == client_end)
+ return SSL_connect(ssl);
+ else
+ return SSL_accept(ssl);
+}
+
+
+int SSL_clear(SSL* ssl)
+{
+ ssl->useSocket().closeSocket();
+ return SSL_SUCCESS;
+}
+
+
+int SSL_shutdown(SSL* ssl)
+{
+ Alert alert(warning, close_notify);
+ sendAlert(*ssl, alert);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);
+ ssl->useSocket().closeSocket();
+
+ return SSL_SUCCESS;
+}
+
+
+SSL_SESSION* SSL_get_session(SSL* ssl)
+{
+ return GetSessions().lookup(
+ ssl->getSecurity().get_connection().sessionID_);
+}
+
+
+int SSL_set_session(SSL* ssl, SSL_SESSION* session)
+{
+ ssl->set_session(session);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_session_reused(SSL* ssl)
+{
+ return ssl->getSecurity().get_resuming();
+}
+
+
+long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t)
+{
+ if (!sess)
+ return SSL_ERROR_NONE;
+
+ sess->SetTimeOut(t);
+ return SSL_SUCCESS;
+}
+
+
+long SSL_get_default_timeout(SSL* /*ssl*/)
+{
+ return DEFAULT_TIMEOUT;
+}
+
+
+const char* SSL_get_cipher_name(SSL* ssl)
+{
+ return SSL_get_cipher(ssl);
+}
+
+
+const char* SSL_get_cipher(SSL* ssl)
+{
+ return ssl->getSecurity().get_parms().cipher_name_;
+}
+
+
+// SSLv2 only, not implemented
+char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len)
+{
+ return strncpy(buf, "Not Implemented, SSLv2 only", len);
+}
+
+
+const char* SSL_get_cipher_list(SSL* ssl, int /*priority */)
+{
+ return ssl->getSecurity().get_parms().cipher_list_;
+}
+
+
+int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
+{
+ if (ctx->SetCipherList(list))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+const char* SSL_get_version(SSL* ssl)
+{
+ static const char* version3 = "SSLv3";
+ static const char* version31 = "TLSv1";
+
+ return ssl->isTLS() ? version31 : version3;
+}
+
+const char* SSLeay_version(int)
+{
+ static const char* version = "SSLeay yaSSL compatibility";
+ return version;
+}
+
+
+int SSL_get_error(SSL* ssl, int /*previous*/)
+{
+ return ssl->getStates().What();
+}
+
+
+X509* SSL_get_peer_certificate(SSL* ssl)
+{
+ return ssl->getCrypto().get_certManager().get_peerX509();
+}
+
+
+void X509_free(X509* /*x*/)
+{
+ // peer cert set for deletion during destruction
+ // no need to delete now
+}
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
+{
+ return ctx->current_cert;
+}
+
+
+int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
+{
+ return ctx->error;
+}
+
+
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
+{
+ return ctx->error_depth;
+}
+
+
+// copy name into buffer, at most sz bytes, if buffer is null
+// will malloc buffer, caller responsible for freeing
+char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
+{
+ if (!name->GetName()) return buffer;
+
+ int len = strlen(name->GetName()) + 1;
+ int copySz = min(len, sz);
+
+ if (!buffer) {
+ buffer = (char*)malloc(len);
+ if (!buffer) return buffer;
+ copySz = len;
+ }
+
+ if (copySz == 0)
+ return buffer;
+
+ memcpy(buffer, name->GetName(), copySz - 1);
+ buffer[copySz - 1] = 0;
+
+ return buffer;
+}
+
+
+X509_NAME* X509_get_issuer_name(X509* x)
+{
+ return x->GetIssuer();
+}
+
+
+X509_NAME* X509_get_subject_name(X509* x)
+{
+ return x->GetSubject();
+}
+
+
+void SSL_load_error_strings() // compatibility only
+{}
+
+
+void SSL_set_connect_state(SSL*)
+{
+ // already a client by default
+}
+
+
+void SSL_set_accept_state(SSL* ssl)
+{
+ ssl->useSecurity().use_parms().entity_ = server_end;
+}
+
+
+long SSL_get_verify_result(SSL*)
+{
+ // won't get here if not OK
+ return X509_V_OK;
+}
+
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX* /*ctx*/, long /*sz*/)
+{
+ // unlimited size, can't set for now
+ return 0;
+}
+
+
+long SSL_CTX_get_session_cache_mode(SSL_CTX*)
+{
+ // always 0, unlimited size for now
+ return 0;
+}
+
+
+long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh)
+{
+ if (ctx->SetDH(*dh))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+int read_file(SSL_CTX* ctx, const char* file, int format, CertType type)
+{
+ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
+ return SSL_BAD_FILETYPE;
+
+ FILE* input = fopen(file, "rb");
+ if (!input)
+ return SSL_BAD_FILE;
+
+ if (type == CA) {
+ x509* ptr = PemToDer(file, Cert);
+ if (!ptr) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ ctx->AddCA(ptr); // takes ownership
+ }
+ else {
+ x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_;
+
+ if (format == SSL_FILETYPE_ASN1) {
+ fseek(input, 0, SEEK_END);
+ long sz = ftell(input);
+ rewind(input);
+ x = new (ys) x509(sz); // takes ownership
+ size_t bytes = fread(x->use_buffer(), sz, 1, input);
+ if (bytes != 1) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ else {
+ x = PemToDer(file, type);
+ if (!x) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ }
+ fclose(input);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, Cert);
+}
+
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, PrivateKey);
+}
+
+
+void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback /*vc*/)
+{
+ if (mode & SSL_VERIFY_PEER)
+ ctx->setVerifyPeer();
+
+ if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ ctx->setFailNoCert();
+}
+
+
+int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
+ const char* /*path*/)
+{
+ // just files for now
+ return read_file(ctx, file, SSL_FILETYPE_PEM, CA);
+}
+
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX* /*ctx*/)
+{
+ // TODO: figure out way to set/store default path, then call load_verify
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int)
+{
+ // No application specific context needed for yaSSL
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_check_private_key(SSL_CTX* /*ctx*/)
+{
+ // TODO: check private against public for RSA match
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+// TODO: all session stats
+long SSL_CTX_sess_accept(SSL_CTX* ctx)
+{
+ return ctx->GetStats().accept_;
+}
+
+
+long SSL_CTX_sess_connect(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connect_;
+}
+
+
+long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptGood_;
+}
+
+
+long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectGood_;
+}
+
+
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptRenegotiate_;
+}
+
+
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectRenegotiate_;
+}
+
+
+long SSL_CTX_sess_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().hits_;
+}
+
+
+long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cbHits_;
+}
+
+
+long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cacheFull_;
+}
+
+
+long SSL_CTX_sess_misses(SSL_CTX* ctx)
+{
+ return ctx->GetStats().misses_;
+}
+
+
+long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
+{
+ return ctx->GetStats().timeouts_;
+}
+
+
+long SSL_CTX_sess_number(SSL_CTX* ctx)
+{
+ return ctx->GetStats().number_;
+}
+
+
+long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
+{
+ return ctx->GetStats().getCacheSize_;
+}
+// end session stats TODO:
+
+
+int SSL_CTX_get_verify_mode(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyMode_;
+}
+
+
+int SSL_get_verify_mode(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyMode_;
+}
+
+
+int SSL_CTX_get_verify_depth(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyDepth_;
+}
+
+
+int SSL_get_verify_depth(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyDepth_;
+}
+
+
+long SSL_CTX_set_options(SSL_CTX*, long)
+{
+ // TDOD:
+ return SSL_SUCCESS;
+}
+
+
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)())
+{
+ // TDOD:
+}
+
+
+void OpenSSL_add_all_algorithms() // compatibility only
+{}
+
+
+DH* DH_new(void)
+{
+ DH* dh = new DH;
+ if (dh)
+ dh->p = dh->g = 0;
+ return dh;
+}
+
+
+void DH_free(DH* dh)
+{
+ delete dh->g;
+ delete dh->p;
+ delete dh;
+}
+
+
+// convert positive big-endian num of length sz into retVal, which may need to
+// be created
+BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal)
+{
+ using mySTL::auto_ptr;
+ bool created = false;
+ auto_ptr<BIGNUM> bn;
+
+ if (!retVal) {
+ created = true;
+ bn.reset(new (ys) BIGNUM);
+ retVal = bn.get();
+ }
+
+ retVal->assign(num, sz);
+
+ if (created)
+ return bn.release();
+ else
+ return retVal;
+}
+
+
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *)
+{
+ //return SSL_NOT_IMPLEMENTED;
+ return 0;
+}
+
+
+void ERR_print_errors_fp(FILE* /*fp*/)
+{
+ // need ssl access to implement TODO:
+ //fprintf(fp, "%s", ssl.get_states().errorString_.c_str());
+}
+
+
+char* ERR_error_string(unsigned long /*err*/, char* buffer)
+{
+ // TODO:
+ static char* msg = "Not Implemented";
+ if (buffer)
+ return strncpy(buffer, msg, strlen(msg));
+
+ return msg;
+}
+
+
+const char* X509_verify_cert_error_string(long /* error */)
+{
+ // TODO:
+ static const char* msg = "Not Implemented";
+ return msg;
+}
+
+
+const EVP_MD* EVP_md5(void)
+{
+ // TODO: FIX add to some list for destruction
+ return new MD5;
+}
+
+
+const EVP_CIPHER* EVP_des_ede3_cbc(void)
+{
+ // TODO: FIX add to some list for destruction
+ return new DES_EDE;
+}
+
+
+int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt,
+ const byte* data, int sz, int count, byte* key, byte* iv)
+{
+ EVP_MD* myMD = const_cast<EVP_MD*>(md);
+ uint digestSz = myMD->get_digestSize();
+ byte digest[SHA_LEN]; // max size
+
+ int keyLen = type->get_keySize();
+ int ivLen = type->get_ivSize();
+ int keyLeft = keyLen;
+ int ivLeft = ivLen;
+ int keyOutput = 0;
+
+ while (keyOutput < (keyLen + ivLen)) {
+ int digestLeft = digestSz;
+ // D_(i - 1)
+ if (keyOutput) // first time D_0 is empty
+ myMD->update(digest, digestSz);
+ // data
+ myMD->update(data, sz);
+ // salt
+ if (salt)
+ myMD->update(salt, EVP_SALT_SZ);
+ myMD->get_digest(digest);
+ // count
+ for (int j = 1; j < count; j++) {
+ myMD->update(digest, digestSz);
+ myMD->get_digest(digest);
+ }
+
+ if (keyLeft) {
+ int store = min(keyLeft, static_cast<int>(digestSz));
+ memcpy(&key[keyLen - keyLeft], digest, store);
+
+ keyOutput += store;
+ keyLeft -= store;
+ digestLeft -= store;
+ }
+
+ if (ivLeft && digestLeft) {
+ int store = min(ivLeft, digestLeft);
+ memcpy(&iv[ivLen - ivLeft], digest, store);
+
+ keyOutput += store;
+ ivLeft -= store;
+ }
+ }
+ assert(keyOutput == (keyLen + ivLen));
+ return keyOutput;
+}
+
+
+
+void DES_set_key_unchecked(const_DES_cblock* key, DES_key_schedule* schedule)
+{
+ memcpy(schedule, key, sizeof(const_DES_cblock));
+}
+
+
+void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
+ DES_key_schedule* ks1, DES_key_schedule* ks2,
+ DES_key_schedule* ks3, DES_cblock* ivec, int enc)
+{
+ DES_EDE des;
+ byte key[DES_EDE_KEY_SZ];
+
+ memcpy(key, *ks1, DES_BLOCK);
+ memcpy(&key[DES_BLOCK], *ks2, DES_BLOCK);
+ memcpy(&key[DES_BLOCK * 2], *ks3, DES_BLOCK);
+
+ if (enc) {
+ des.set_encryptKey(key, *ivec);
+ des.encrypt(output, input, sz);
+ }
+ else {
+ des.set_decryptKey(key, *ivec);
+ des.decrypt(output, input, sz);
+ }
+}
+
+
+ // functions for stunnel
+
+ void RAND_screen()
+ {
+ // TODO:
+ }
+
+
+ const char* RAND_file_name(char*, size_t)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_write_file(const char*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_load_file(const char*, long)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void RSA_free(RSA*)
+ {
+ // TODO:
+ }
+
+
+ RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, X509_OBJECT*)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_STORE* X509_STORE_new(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+ char* SSL_alert_type_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_alert_desc_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_state_string_long(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int))
+ {
+ // TDOD:
+ }
+
+
+ long SSL_CTX_set_session_cache_mode(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_set_timeout(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb)
+ {
+ // TDOD:
+ }
+
+
+ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_set_rfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_set_wfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_pending(SSL*)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_want_read(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ int SSL_want_write(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ void SSL_set_shutdown(SSL*, int)
+ {
+ // TODO:
+ }
+
+
+ SSL_CIPHER* SSL_get_current_cipher(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_CIPHER_description(SSL_CIPHER*, char*, int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSLeay_add_ssl_algorithms() // compatibility only
+ {}
+
+
+ void ERR_remove_state(unsigned long)
+ {
+ // TODO:
+ }
+
+
+ int ERR_GET_REASON(int l)
+ {
+ return l & 0xfff;
+ }
+
+
+ unsigned long ERR_peek_error()
+ {
+ return 0; // TODO:
+ }
+
+
+ unsigned long ERR_get_error()
+ {
+ return ERR_peek_error();
+ }
+
+
+ // end stunnel needs
+
+
+} // namespace
diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp
new file mode 100644
index 00000000000..49e7bb36776
--- /dev/null
+++ b/extra/yassl/src/timer.cpp
@@ -0,0 +1,82 @@
+ /* timer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* timer.cpp implements a high res and low res timer
+ *
+*/
+
+#include "runtime.hpp"
+#include "timer.hpp"
+
+namespace yaSSL {
+
+#ifdef WIN32
+
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+
+ timer_d timer()
+ {
+ static bool init(false);
+ static LARGE_INTEGER freq;
+
+ if (!init) {
+ QueryPerformanceFrequency(&freq);
+ init = true;
+ }
+
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+
+ return static_cast<double>(count.QuadPart) / freq.QuadPart;
+ }
+
+
+ uint lowResTimer()
+ {
+ return static_cast<uint>(timer());
+ }
+
+#else // WIN32
+
+ #include <sys/time.h>
+
+ timer_d timer()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return static_cast<double>(tv.tv_sec)
+ + static_cast<double>(tv.tv_usec) / 1000000;
+ }
+
+
+ uint lowResTimer()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return tv.tv_sec;
+ }
+
+
+#endif // WIN32
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp
new file mode 100644
index 00000000000..c53aef2068d
--- /dev/null
+++ b/extra/yassl/src/yassl_error.cpp
@@ -0,0 +1,53 @@
+/* yassl_error.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL error implements and an exception class
+ */
+
+#include "runtime.hpp"
+#include "yassl_error.hpp"
+
+namespace yaSSL {
+
+
+Error::Error(const char* s, YasslError e, Library l)
+ : mySTL::runtime_error(s), error_(e), lib_(l)
+{
+}
+
+
+YasslError Error::get_number() const
+{
+ return error_;
+}
+
+
+Library Error::get_lib() const
+{
+
+ return lib_;
+}
+
+
+
+
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
new file mode 100644
index 00000000000..c1485cce986
--- /dev/null
+++ b/extra/yassl/src/yassl_imp.cpp
@@ -0,0 +1,2118 @@
+/* yassl_imp.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* yaSSL source implements all SSL.v3 secification structures.
+ */
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+
+#include "asn.hpp" // provide crypto wrapper??
+
+
+namespace yaSSL {
+
+
+namespace { // locals
+
+bool isTLS(ProtocolVersion pv)
+{
+ if (pv.major_ >= 3 && pv.minor_ >= 1)
+ return true;
+
+ return false;
+}
+
+
+} // namespace (locals)
+
+
+void hashHandShake(SSL&, const input_buffer&, uint);
+
+
+ProtocolVersion::ProtocolVersion(uint8 maj, uint8 min)
+ : major_(maj), minor_(min)
+{}
+
+
+// construct key exchange with known ssl parms
+void ClientKeyExchange::createKey(SSL& ssl)
+{
+ const ClientKeyFactory& ckf = ssl.getFactory().getClientKey();
+ client_key_ = ckf.CreateObject(ssl.getSecurity().get_parms().kea_);
+
+ if (!client_key_)
+ ssl.SetError(factory_error);
+}
+
+
+// construct key exchange with known ssl parms
+void ServerKeyExchange::createKey(SSL& ssl)
+{
+ const ServerKeyFactory& skf = ssl.getFactory().getServerKey();
+ server_key_ = skf.CreateObject(ssl.getSecurity().get_parms().kea_);
+
+ if (!server_key_)
+ ssl.SetError(factory_error);
+}
+
+
+// build/set PreMaster secret and encrypt, client side
+void EncryptedPreMasterSecret::build(SSL& ssl)
+{
+ opaque tmp[SECRET_LEN];
+ memset(tmp, 0, sizeof(tmp));
+ ssl.getCrypto().get_random().Fill(tmp, SECRET_LEN);
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ tmp[0] = pv.major_;
+ tmp[1] = pv.minor_;
+ ssl.set_preMaster(tmp, SECRET_LEN);
+
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+ bool tls = ssl.isTLS(); // if TLS, put length for encrypted data
+ alloc(rsa.get_cipherLength() + (tls ? 2 : 0));
+ byte* holder = secret_;
+ if (tls) {
+ byte len[2];
+ c16toa(rsa.get_cipherLength(), len);
+ memcpy(secret_, len, sizeof(len));
+ holder += 2;
+ }
+ rsa.encrypt(holder, tmp, SECRET_LEN, ssl.getCrypto().get_random());
+}
+
+
+// build/set premaster and Client Public key, client side
+void ClientDiffieHellmanPublic::build(SSL& ssl)
+{
+ DiffieHellman& dhServer = ssl.useCrypto().use_dh();
+ DiffieHellman dhClient(dhServer);
+
+ uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same
+
+ alloc(keyLength, true);
+ dhClient.makeAgreement(dhServer.get_publicKey());
+ c16toa(keyLength, Yc_);
+ memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength);
+
+ ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);
+}
+
+
+// build server exhange, server side
+void DH_Server::build(SSL& ssl)
+{
+ DiffieHellman& dhServer = ssl.useCrypto().use_dh();
+
+ int pSz, gSz, pubSz;
+ dhServer.set_sizes(pSz, gSz, pubSz);
+ dhServer.get_parms(parms_.alloc_p(pSz), parms_.alloc_g(gSz),
+ parms_.alloc_pub(pubSz));
+
+ short sigSz = 0;
+ mySTL::auto_ptr<Auth> auth;
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo)
+ auth.reset(new (ys) RSA(cert.get_privateKey(),
+ cert.get_privateKeyLength(), false));
+ else {
+ auth.reset(new (ys) DSS(cert.get_privateKey(),
+ cert.get_privateKeyLength(), false));
+ sigSz += DSS_ENCODED_EXTRA;
+ }
+
+
+ sigSz += auth->get_signatureLength();
+
+
+ length_ = 8; // pLen + gLen + YsLen + SigLen
+ length_ += pSz + gSz + pubSz + sigSz;
+
+ output_buffer tmp(length_);
+ byte len[2];
+ // P
+ c16toa(pSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_p(), pSz);
+ // G
+ c16toa(gSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_g(), gSz);
+ // Ys
+ c16toa(pubSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_pub(), pubSz);
+
+ // Sig
+ byte hash[FINISHED_SZ];
+ MD5 md5;
+ SHA sha;
+ signature_ = new (ys) byte[sigSz];
+
+ const Connection& conn = ssl.getSecurity().get_connection();
+ // md5
+ md5.update(conn.client_random_, RAN_LEN);
+ md5.update(conn.server_random_, RAN_LEN);
+ md5.update(tmp.get_buffer(), tmp.get_size());
+ md5.get_digest(hash);
+
+ // sha
+ sha.update(conn.client_random_, RAN_LEN);
+ sha.update(conn.server_random_, RAN_LEN);
+ sha.update(tmp.get_buffer(), tmp.get_size());
+ sha.get_digest(&hash[MD5_LEN]);
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo)
+ auth->sign(signature_, hash, sizeof(hash),
+ ssl.getCrypto().get_random());
+ else {
+ auth->sign(signature_, &hash[MD5_LEN], SHA_LEN,
+ ssl.getCrypto().get_random());
+ byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA];
+ TaoCrypt::EncodeDSA_Signature(signature_, encoded);
+ memcpy(signature_, encoded, sizeof(encoded));
+ }
+
+ c16toa(sigSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(signature_, sigSz);
+
+ // key message
+ keyMessage_ = new (ys) opaque[length_];
+ memcpy(keyMessage_, tmp.get_buffer(), tmp.get_size());
+}
+
+
+// read PreMaster secret and decrypt, server side
+void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input)
+{
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+ uint16 cipherLen = rsa.get_cipherLength();
+ if (ssl.isTLS()) {
+ byte len[2];
+ input.read(len, sizeof(len));
+ ato16(len, cipherLen);
+ }
+ alloc(cipherLen);
+ input.read(secret_, length_);
+
+ opaque preMasterSecret[SECRET_LEN];
+ rsa.decrypt(preMasterSecret, secret_, length_,
+ ssl.getCrypto().get_random());
+
+ ssl.set_preMaster(preMasterSecret, SECRET_LEN);
+ ssl.makeMasterSecret();
+}
+
+
+EncryptedPreMasterSecret::EncryptedPreMasterSecret()
+ : secret_(0), length_(0)
+{}
+
+
+EncryptedPreMasterSecret::~EncryptedPreMasterSecret()
+{
+ delete[] secret_;
+}
+
+
+int EncryptedPreMasterSecret::get_length() const
+{
+ return length_;
+}
+
+
+opaque* EncryptedPreMasterSecret::get_clientKey() const
+{
+ return secret_;
+}
+
+
+void EncryptedPreMasterSecret::alloc(int sz)
+{
+ length_ = sz;
+ secret_ = new (ys) opaque[sz];
+}
+
+
+// read client's public key, server side
+void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
+{
+ DiffieHellman& dh = ssl.useCrypto().use_dh();
+
+ uint16 keyLength;
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, keyLength);
+
+ alloc(keyLength);
+ input.read(Yc_, length_);
+ dh.makeAgreement(Yc_);
+
+ ssl.set_preMaster(dh.get_agreedKey(), keyLength);
+ ssl.makeMasterSecret();
+}
+
+
+ClientDiffieHellmanPublic::ClientDiffieHellmanPublic()
+ : length_(0), Yc_(0)
+{}
+
+
+ClientDiffieHellmanPublic::~ClientDiffieHellmanPublic()
+{
+ delete[] Yc_;
+}
+
+
+int ClientDiffieHellmanPublic::get_length() const
+{
+ return length_;
+}
+
+
+opaque* ClientDiffieHellmanPublic::get_clientKey() const
+{
+ return Yc_;
+}
+
+
+void ClientDiffieHellmanPublic::alloc(int sz, bool offset)
+{
+ length_ = sz + (offset ? KEY_OFFSET : 0);
+ Yc_ = new (ys) opaque[length_];
+}
+
+
+// read server's p, g, public key and sig, client side
+void DH_Server::read(SSL& ssl, input_buffer& input)
+{
+ uint16 length, messageTotal = 6; // pSz + gSz + pubSz
+ byte tmp[2];
+
+ // p
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_p(length), length);
+
+ // g
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_g(length), length);
+
+ // pub
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_pub(length), length);
+
+ // save message for hash verify
+ input_buffer message(messageTotal);
+ input.set_current(input.get_current() - messageTotal);
+ input.read(message.get_buffer(), messageTotal);
+ message.add_size(messageTotal);
+
+ // signature
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+
+ signature_ = new (ys) byte[length];
+ input.read(signature_, length);
+
+ // verify signature
+ byte hash[FINISHED_SZ];
+ MD5 md5;
+ SHA sha;
+
+ const Connection& conn = ssl.getSecurity().get_connection();
+ // md5
+ md5.update(conn.client_random_, RAN_LEN);
+ md5.update(conn.server_random_, RAN_LEN);
+ md5.update(message.get_buffer(), message.get_size());
+ md5.get_digest(hash);
+
+ // sha
+ sha.update(conn.client_random_, RAN_LEN);
+ sha.update(conn.server_random_, RAN_LEN);
+ sha.update(message.get_buffer(), message.get_size());
+ sha.get_digest(&hash[MD5_LEN]);
+
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) {
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!rsa.verify(hash, sizeof(hash), signature_, length))
+ ssl.SetError(verify_error);
+ }
+ else {
+ byte decodedSig[DSS_SIG_SZ];
+ length = TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, length);
+
+ DSS dss(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!dss.verify(&hash[MD5_LEN], SHA_LEN, decodedSig, length))
+ ssl.SetError(verify_error);
+ }
+
+ // save input
+ ssl.useCrypto().SetDH(new (ys) DiffieHellman(parms_.get_p(),
+ parms_.get_pSize(), parms_.get_g(), parms_.get_gSize(),
+ parms_.get_pub(), parms_.get_pubSize(),
+ ssl.getCrypto().get_random()));
+}
+
+
+DH_Server::DH_Server()
+ : signature_(0), length_(0), keyMessage_(0)
+{}
+
+
+DH_Server::~DH_Server()
+{
+ delete[] keyMessage_;
+ delete[] signature_;
+}
+
+
+int DH_Server::get_length() const
+{
+ return length_;
+}
+
+
+opaque* DH_Server::get_serverKey() const
+{
+ return keyMessage_;
+}
+
+
+// set available suites
+Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers,
+ ProtocolVersion pv) : entity_(ce)
+{
+ pending_ = true; // suite not set yet
+
+ if (ciphers.setSuites_) { // use user set list
+ suites_size_ = ciphers.suiteSz_;
+ memcpy(suites_, ciphers.suites_, ciphers.suiteSz_);
+ SetCipherNames();
+ }
+ else
+ SetSuites(pv); // defaults
+}
+
+
+void Parameters::SetSuites(ProtocolVersion pv)
+{
+ int i = 0;
+ // available suites, best first
+ // when adding more, make sure cipher_names is updated and
+ // MAX_CIPHER_LIST is big enough
+
+ if (isTLS(pv)) {
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_3DES_EDE_CBC_RMD160;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160;
+ }
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_RC4_128_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_RC4_128_MD5;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_DES_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_DSS_WITH_DES_CBC_SHA;
+
+ suites_size_ = i;
+
+ SetCipherNames();
+}
+
+
+void Parameters::SetCipherNames()
+{
+ const int suites = suites_size_ / 2;
+ int pos = 0;
+
+ for (int j = 0; j < suites; j++) {
+ int index = suites_[j*2 + 1]; // every other suite is suite id
+ int len = strlen(cipher_names[index]);
+ memcpy(&cipher_list_[pos], cipher_names[index], len);
+ pos += len;
+ cipher_list_[pos++] = ':';
+ }
+ if (suites)
+ cipher_list_[--pos] = 0;
+}
+
+
+// input operator for RecordLayerHeader, adjust stream
+input_buffer& operator>>(input_buffer& input, RecordLayerHeader& hdr)
+{
+ hdr.type_ = ContentType(input[AUTO]);
+ hdr.version_.major_ = input[AUTO];
+ hdr.version_.minor_ = input[AUTO];
+
+ // length
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, hdr.length_);
+
+ return input;
+}
+
+
+// output operator for RecordLayerHeader
+output_buffer& operator<<(output_buffer& output, const RecordLayerHeader& hdr)
+{
+ output[AUTO] = hdr.type_;
+ output[AUTO] = hdr.version_.major_;
+ output[AUTO] = hdr.version_.minor_;
+
+ // length
+ byte tmp[2];
+ c16toa(hdr.length_, tmp);
+ output[AUTO] = tmp[0];
+ output[AUTO] = tmp[1];
+
+ return output;
+}
+
+
+// virtual input operator for Messages
+input_buffer& operator>>(input_buffer& input, Message& msg)
+{
+ return msg.set(input);
+}
+
+// virtual output operator for Messages
+output_buffer& operator<<(output_buffer& output, const Message& msg)
+{
+ return msg.get(output);
+}
+
+
+// input operator for HandShakeHeader
+input_buffer& operator>>(input_buffer& input, HandShakeHeader& hs)
+{
+ hs.type_ = HandShakeType(input[AUTO]);
+
+ hs.length_[0] = input[AUTO];
+ hs.length_[1] = input[AUTO];
+ hs.length_[2] = input[AUTO];
+
+ return input;
+}
+
+
+// output operator for HandShakeHeader
+output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr)
+{
+ output[AUTO] = hdr.type_;
+ output.write(hdr.length_, sizeof(hdr.length_));
+ return output;
+}
+
+
+// HandShake Header Processing function
+void HandShakeHeader::Process(input_buffer& input, SSL& ssl)
+{
+ ssl.verifyState(*this);
+ const HandShakeFactory& hsf = ssl.getFactory().getHandShake();
+ mySTL::auto_ptr<HandShakeBase> hs(hsf.CreateObject(type_));
+ if (!hs.get()) {
+ ssl.SetError(factory_error);
+ return;
+ }
+ hashHandShake(ssl, input, c24to32(length_));
+
+ input >> *hs;
+ hs->Process(input, ssl);
+}
+
+
+ContentType HandShakeHeader::get_type() const
+{
+ return handshake;
+}
+
+
+uint16 HandShakeHeader::get_length() const
+{
+ return c24to32(length_);
+}
+
+
+HandShakeType HandShakeHeader::get_handshakeType() const
+{
+ return type_;
+}
+
+
+void HandShakeHeader::set_type(HandShakeType hst)
+{
+ type_ = hst;
+}
+
+
+void HandShakeHeader::set_length(uint32 u32)
+{
+ c32to24(u32, length_);
+}
+
+
+input_buffer& HandShakeHeader::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& HandShakeHeader::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+
+int HandShakeBase::get_length() const
+{
+ return length_;
+}
+
+
+void HandShakeBase::set_length(int l)
+{
+ length_ = l;
+}
+
+
+// for building buffer's type field
+HandShakeType HandShakeBase::get_type() const
+{
+ return no_shake;
+}
+
+
+input_buffer& HandShakeBase::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& HandShakeBase::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+void HandShakeBase::Process(input_buffer&, SSL&)
+{}
+
+
+input_buffer& HelloRequest::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& HelloRequest::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+void HelloRequest::Process(input_buffer&, SSL&)
+{}
+
+
+HandShakeType HelloRequest::get_type() const
+{
+ return hello_request;
+}
+
+
+// input operator for CipherSpec
+input_buffer& operator>>(input_buffer& input, ChangeCipherSpec& cs)
+{
+ cs.type_ = CipherChoice(input[AUTO]);
+ return input;
+}
+
+// output operator for CipherSpec
+output_buffer& operator<<(output_buffer& output, const ChangeCipherSpec& cs)
+{
+ output[AUTO] = cs.type_;
+ return output;
+}
+
+
+ChangeCipherSpec::ChangeCipherSpec()
+ : type_(change_cipher_spec_choice)
+{}
+
+
+input_buffer& ChangeCipherSpec::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ChangeCipherSpec::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+ContentType ChangeCipherSpec::get_type() const
+{
+ return change_cipher_spec;
+}
+
+
+uint16 ChangeCipherSpec::get_length() const
+{
+ return SIZEOF_ENUM;
+}
+
+
+// CipherSpec processing handler
+void ChangeCipherSpec::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useSecurity().use_parms().pending_ = false;
+ if (ssl.getSecurity().get_resuming()) {
+ if (ssl.getSecurity().get_parms().entity_ == client_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
+ }
+ else if (ssl.getSecurity().get_parms().entity_ == server_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
+}
+
+
+Alert::Alert(AlertLevel al, AlertDescription ad)
+ : level_(al), description_(ad)
+{}
+
+
+ContentType Alert::get_type() const
+{
+ return alert;
+}
+
+
+uint16 Alert::get_length() const
+{
+ return SIZEOF_ENUM * 2;
+}
+
+
+input_buffer& Alert::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& Alert::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for Alert
+input_buffer& operator>>(input_buffer& input, Alert& a)
+{
+ a.level_ = AlertLevel(input[AUTO]);
+ a.description_ = AlertDescription(input[AUTO]);
+
+ return input;
+}
+
+
+// output operator for Alert
+output_buffer& operator<<(output_buffer& output, const Alert& a)
+{
+ output[AUTO] = a.level_;
+ output[AUTO] = a.description_;
+ return output;
+}
+
+
+// Alert processing handler
+void Alert::Process(input_buffer& input, SSL& ssl)
+{
+ if (ssl.getSecurity().get_parms().pending_ == false) { // encrypted alert
+ int aSz = get_length(); // alert size already read on input
+ opaque verify[SHA_LEN];
+ const opaque* data = input.get_buffer() + input.get_current() - aSz;
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verify, data, aSz, alert, true);
+ else
+ hmac(ssl, verify, data, aSz, alert, true);
+
+ // read mac and fill
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ opaque mac[SHA_LEN];
+ input.read(mac, digestSz);
+
+ opaque fill;
+ int padSz = ssl.getSecurity().get_parms().encrypt_size_ - aSz -
+ digestSz;
+ for (int i = 0; i < padSz; i++)
+ fill = input[AUTO];
+
+ // verify
+ if (memcmp(mac, verify, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+ }
+ if (level_ == fatal) {
+ ssl.useStates().useRecord() = recordNotReady;
+ ssl.useStates().useHandShake() = handShakeNotReady;
+ ssl.SetError(YasslError(description_));
+ }
+}
+
+
+Data::Data()
+ : length_(0), buffer_(0), write_buffer_(0)
+{}
+
+
+Data::Data(uint16 len, opaque* b)
+ : length_(len), buffer_(b), write_buffer_(0)
+{}
+
+
+Data::Data(uint16 len, const opaque* w)
+ : length_(len), buffer_(0), write_buffer_(w)
+{}
+
+input_buffer& Data::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& Data::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+ContentType Data::get_type() const
+{
+ return application_data;
+}
+
+
+uint16 Data::get_length() const
+{
+ return length_;
+}
+
+
+const opaque* Data::get_buffer() const
+{
+ return write_buffer_;
+}
+
+
+void Data::set_length(uint16 l)
+{
+ length_ = l;
+}
+
+opaque* Data::set_buffer()
+{
+ return buffer_;
+}
+
+
+// output operator for Data
+output_buffer& operator<<(output_buffer& output, const Data& data)
+{
+ output.write(data.write_buffer_, data.length_);
+ return output;
+}
+
+
+// Process handler for Data
+void Data::Process(input_buffer& input, SSL& ssl)
+{
+ int msgSz = ssl.getSecurity().get_parms().encrypt_size_;
+ int pad = 0, padByte = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ pad = *(input.get_buffer() + input.get_current() + msgSz - 1);
+ padByte = 1;
+ }
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ int dataSz = msgSz - digestSz - pad - padByte;
+ opaque verify[SHA_LEN];
+
+ // read data
+ if (dataSz) {
+ input_buffer* data;
+ ssl.addData(data = new (ys) input_buffer(dataSz));
+ input.read(data->get_buffer(), dataSz);
+ data->add_size(dataSz);
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verify, data->get_buffer(), dataSz, application_data,
+ true);
+ else
+ hmac(ssl, verify, data->get_buffer(), dataSz, application_data,
+ true);
+ }
+
+ // read mac and fill
+ opaque mac[SHA_LEN];
+ opaque fill;
+ input.read(mac, digestSz);
+ for (int i = 0; i < pad; i++)
+ fill = input[AUTO];
+ if (padByte)
+ fill = input[AUTO];
+
+ // verify
+ if (dataSz) {
+ if (memcmp(mac, verify, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+ }
+ else
+ ssl.get_SEQIncrement(true); // even though no data, increment verify
+}
+
+
+// virtual input operator for HandShakes
+input_buffer& operator>>(input_buffer& input, HandShakeBase& hs)
+{
+ return hs.set(input);
+}
+
+
+// virtual output operator for HandShakes
+output_buffer& operator<<(output_buffer& output, const HandShakeBase& hs)
+{
+ return hs.get(output);
+}
+
+
+Certificate::Certificate(const x509* cert) : cert_(cert)
+{
+ set_length(cert_->get_length() + 2 * CERT_HEADER); // list and cert size
+}
+
+
+const opaque* Certificate::get_buffer() const
+{
+ return cert_->get_buffer();
+}
+
+
+// output operator for Certificate
+output_buffer& operator<<(output_buffer& output, const Certificate& cert)
+{
+ uint sz = cert.get_length() - 2 * CERT_HEADER;
+ opaque tmp[CERT_HEADER];
+
+ c32to24(sz + CERT_HEADER, tmp);
+ output.write(tmp, CERT_HEADER);
+ c32to24(sz, tmp);
+ output.write(tmp, CERT_HEADER);
+ output.write(cert.get_buffer(), sz);
+
+ return output;
+}
+
+
+// certificate processing handler
+void Certificate::Process(input_buffer& input, SSL& ssl)
+{
+ CertManager& cm = ssl.useCrypto().use_certManager();
+
+ uint32 list_sz;
+ byte tmp[3];
+
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ tmp[2] = input[AUTO];
+ c24to32(tmp, list_sz);
+
+ while (list_sz) {
+ // cert size
+ uint32 cert_sz;
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ tmp[2] = input[AUTO];
+ c24to32(tmp, cert_sz);
+
+ x509* myCert;
+ cm.AddPeerCert(myCert = new (ys) x509(cert_sz));
+ input.read(myCert->use_buffer(), myCert->get_length());
+
+ list_sz -= cert_sz + CERT_HEADER;
+ }
+ if (int err = cm.Validate())
+ ssl.SetError(YasslError(err));
+ else if (ssl.getSecurity().get_parms().entity_ == client_end)
+ ssl.useStates().useClient() = serverCertComplete;
+}
+
+
+Certificate::Certificate()
+ : cert_(0)
+{}
+
+
+input_buffer& Certificate::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& Certificate::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType Certificate::get_type() const
+{
+ return certificate;
+}
+
+
+ServerDHParams::ServerDHParams()
+ : pSz_(0), gSz_(0), pubSz_(0), p_(0), g_(0), Ys_(0)
+{}
+
+
+ServerDHParams::~ServerDHParams()
+{
+ delete[] Ys_;
+ delete[] g_;
+ delete[] p_;
+}
+
+
+int ServerDHParams::get_pSize() const
+{
+ return pSz_;
+}
+
+
+int ServerDHParams::get_gSize() const
+{
+ return gSz_;
+}
+
+
+int ServerDHParams::get_pubSize() const
+{
+ return pubSz_;
+}
+
+
+const opaque* ServerDHParams::get_p() const
+{
+ return p_;
+}
+
+
+const opaque* ServerDHParams::get_g() const
+{
+ return g_;
+}
+
+
+const opaque* ServerDHParams::get_pub() const
+{
+ return Ys_;
+}
+
+
+opaque* ServerDHParams::alloc_p(int sz)
+{
+ p_ = new (ys) opaque[pSz_ = sz];
+ return p_;
+}
+
+
+opaque* ServerDHParams::alloc_g(int sz)
+{
+ g_ = new (ys) opaque[gSz_ = sz];
+ return g_;
+}
+
+
+opaque* ServerDHParams::alloc_pub(int sz)
+{
+ Ys_ = new (ys) opaque[pubSz_ = sz];
+ return Ys_;
+}
+
+
+int ServerKeyBase::get_length() const
+{
+ return 0;
+}
+
+
+opaque* ServerKeyBase::get_serverKey() const
+{
+ return 0;
+}
+
+
+// input operator for ServerHello
+input_buffer& operator>>(input_buffer& input, ServerHello& hello)
+{
+ // Protocol
+ hello.server_version_.major_ = input[AUTO];
+ hello.server_version_.minor_ = input[AUTO];
+
+ // Random
+ input.read(hello.random_, RAN_LEN);
+
+ // Session
+ hello.id_len_ = input[AUTO];
+ input.read(hello.session_id_, ID_LEN);
+
+ // Suites
+ hello.cipher_suite_[0] = input[AUTO];
+ hello.cipher_suite_[1] = input[AUTO];
+
+ // Compression
+ hello.compression_method_ = CompressionMethod(input[AUTO]);
+
+ return input;
+}
+
+
+// output operator for ServerHello
+output_buffer& operator<<(output_buffer& output, const ServerHello& hello)
+{
+ // Protocol
+ output[AUTO] = hello.server_version_.major_;
+ output[AUTO] = hello.server_version_.minor_;
+
+ // Random
+ output.write(hello.random_, RAN_LEN);
+
+ // Session
+ output[AUTO] = hello.id_len_;
+ output.write(hello.session_id_, ID_LEN);
+
+ // Suites
+ output[AUTO] = hello.cipher_suite_[0];
+ output[AUTO] = hello.cipher_suite_[1];
+
+ // Compression
+ output[AUTO] = hello.compression_method_;
+
+ return output;
+}
+
+
+// Server Hello processing handler
+void ServerHello::Process(input_buffer&, SSL& ssl)
+{
+ ssl.set_pending(cipher_suite_[1]);
+ ssl.set_random(random_, server_end);
+ ssl.set_sessionID(session_id_);
+
+ if (ssl.getSecurity().get_resuming())
+ if (memcmp(session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN) == 0) {
+ ssl.set_masterSecret(ssl.getSecurity().get_resume().GetSecret());
+ if (ssl.isTLS())
+ ssl.deriveTLSKeys();
+ else
+ ssl.deriveKeys();
+ ssl.useStates().useClient() = serverHelloDoneComplete;
+ return;
+ }
+ else {
+ ssl.useSecurity().set_resuming(false);
+ ssl.useLog().Trace("server denied resumption");
+ }
+ ssl.useStates().useClient() = serverHelloComplete;
+}
+
+
+ServerHello::ServerHello()
+{
+ memset(random_, 0, RAN_LEN);
+ memset(session_id_, 0, ID_LEN);
+}
+
+
+ServerHello::ServerHello(ProtocolVersion pv)
+ : server_version_(pv)
+{
+ memset(random_, 0, RAN_LEN);
+ memset(session_id_, 0, ID_LEN);
+}
+
+
+input_buffer& ServerHello::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ServerHello::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ServerHello::get_type() const
+{
+ return server_hello;
+}
+
+
+const opaque* ServerHello::get_random() const
+{
+ return random_;
+}
+
+
+// Server Hello Done processing handler
+void ServerHelloDone::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useStates().useClient() = serverHelloDoneComplete;
+}
+
+
+ServerHelloDone::ServerHelloDone()
+{
+ set_length(0);
+}
+
+
+input_buffer& ServerHelloDone::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& ServerHelloDone::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+HandShakeType ServerHelloDone::get_type() const
+{
+ return server_hello_done;
+}
+
+
+int ClientKeyBase::get_length() const
+{
+ return 0;
+}
+
+
+opaque* ClientKeyBase::get_clientKey() const
+{
+ return 0;
+}
+
+
+// input operator for Client Hello
+input_buffer& operator>>(input_buffer& input, ClientHello& hello)
+{
+ // Protocol
+ hello.client_version_.major_ = input[AUTO];
+ hello.client_version_.minor_ = input[AUTO];
+
+ // Random
+ input.read(hello.random_, RAN_LEN);
+
+ // Session
+ hello.id_len_ = input[AUTO];
+ if (hello.id_len_) input.read(hello.session_id_, ID_LEN);
+
+ // Suites
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, hello.suite_len_);
+ input.read(hello.cipher_suites_, hello.suite_len_);
+
+ // Compression
+ hello.comp_len_ = input[AUTO];
+ hello.compression_methods_ = CompressionMethod(input[AUTO]);
+
+ return input;
+}
+
+
+// output operaotr for Client Hello
+output_buffer& operator<<(output_buffer& output, const ClientHello& hello)
+{
+ // Protocol
+ output[AUTO] = hello.client_version_.major_;
+ output[AUTO] = hello.client_version_.minor_;
+
+ // Random
+ output.write(hello.random_, RAN_LEN);
+
+ // Session
+ output[AUTO] = hello.id_len_;
+ if (hello.id_len_) output.write(hello.session_id_, ID_LEN);
+
+ // Suites
+ byte tmp[2];
+ c16toa(hello.suite_len_, tmp);
+ output[AUTO] = tmp[0];
+ output[AUTO] = tmp[1];
+ output.write(hello.cipher_suites_, hello.suite_len_);
+
+ // Compression
+ output[AUTO] = hello.comp_len_;
+ output[AUTO] = hello.compression_methods_;
+
+ return output;
+}
+
+
+// Client Hello processing handler
+void ClientHello::Process(input_buffer&, SSL& ssl)
+{
+ if (ssl.isTLS() && client_version_.minor_ == 0) {
+ ssl.useSecurity().use_connection().TurnOffTLS();
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites
+ }
+ ssl.set_random(random_, client_end);
+
+ while (id_len_) { // trying to resume
+ SSL_SESSION* session = GetSessions().lookup(session_id_);
+ if (!session) {
+ ssl.useLog().Trace("session lookup failed");
+ break;
+ }
+ ssl.set_session(session);
+ ssl.useSecurity().set_resuming(true);
+ ssl.matchSuite(session->GetSuite(), SUITE_LEN);
+ ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]);
+ ssl.set_masterSecret(session->GetSecret());
+
+ opaque serverRandom[RAN_LEN];
+ ssl.getCrypto().get_random().Fill(serverRandom, sizeof(serverRandom));
+ ssl.set_random(serverRandom, server_end);
+ if (ssl.isTLS())
+ ssl.deriveTLSKeys();
+ else
+ ssl.deriveKeys();
+ ssl.useStates().useServer() = clientKeyExchangeComplete;
+ return;
+ }
+ ssl.matchSuite(cipher_suites_, suite_len_);
+ ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]);
+
+ ssl.useStates().useServer() = clientHelloComplete;
+}
+
+
+input_buffer& ClientHello::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ClientHello::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ClientHello::get_type() const
+{
+ return client_hello;
+}
+
+
+const opaque* ClientHello::get_random() const
+{
+ return random_;
+}
+
+
+ClientHello::ClientHello()
+{
+ memset(random_, 0, RAN_LEN);
+}
+
+
+ClientHello::ClientHello(ProtocolVersion pv)
+ : client_version_(pv)
+{
+ memset(random_, 0, RAN_LEN);
+}
+
+
+// output operator for ServerKeyExchange
+output_buffer& operator<<(output_buffer& output, const ServerKeyExchange& sk)
+{
+ output.write(sk.getKey(), sk.getKeyLength());
+ return output;
+}
+
+
+// Server Key Exchange processing handler
+void ServerKeyExchange::Process(input_buffer& input, SSL& ssl)
+{
+ createKey(ssl);
+ if (ssl.GetError()) return;
+ server_key_->read(ssl, input);
+
+ ssl.useStates().useClient() = serverKeyExchangeComplete;
+}
+
+
+ServerKeyExchange::ServerKeyExchange(SSL& ssl)
+{
+ createKey(ssl);
+}
+
+
+ServerKeyExchange::ServerKeyExchange()
+ : server_key_(0)
+{}
+
+
+ServerKeyExchange::~ServerKeyExchange()
+{
+ delete server_key_;
+}
+
+
+void ServerKeyExchange::build(SSL& ssl)
+{
+ server_key_->build(ssl);
+ set_length(server_key_->get_length());
+}
+
+
+const opaque* ServerKeyExchange::getKey() const
+{
+ return server_key_->get_serverKey();
+}
+
+
+int ServerKeyExchange::getKeyLength() const
+{
+ return server_key_->get_length();
+}
+
+
+input_buffer& ServerKeyExchange::set(input_buffer& in)
+{
+ return in; // process does
+}
+
+
+output_buffer& ServerKeyExchange::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ServerKeyExchange::get_type() const
+{
+ return server_key_exchange;
+}
+
+
+// CertificateRequest
+CertificateRequest::CertificateRequest()
+ : typeTotal_(0)
+{
+ memset(certificate_types_, 0, sizeof(certificate_types_));
+}
+
+
+CertificateRequest::~CertificateRequest()
+{
+
+ mySTL::for_each(certificate_authorities_.begin(),
+ certificate_authorities_.end(),
+ del_ptr_zero()) ;
+}
+
+
+void CertificateRequest::Build()
+{
+ certificate_types_[0] = rsa_sign;
+ certificate_types_[1] = dss_sign;
+
+ typeTotal_ = 2;
+
+ uint16 authCount = 0;
+ uint16 authSz = 0;
+
+ for (int j = 0; j < authCount; j++) {
+ int sz = REQUEST_HEADER + MIN_DIS_SIZE;
+ DistinguishedName dn;
+ certificate_authorities_.push_back(dn = new (ys) byte[sz]);
+
+ opaque tmp[REQUEST_HEADER];
+ c16toa(MIN_DIS_SIZE, tmp);
+ memcpy(dn, tmp, sizeof(tmp));
+
+ // fill w/ junk for now
+ memcpy(dn, tmp, MIN_DIS_SIZE);
+ authSz += sz;
+ }
+
+ set_length(SIZEOF_ENUM + typeTotal_ + REQUEST_HEADER + authSz);
+}
+
+
+input_buffer& CertificateRequest::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& CertificateRequest::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for CertificateRequest
+input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
+{
+ // types
+ request.typeTotal_ = input[AUTO];
+ for (int i = 0; i < request.typeTotal_; i++)
+ request.certificate_types_[i] = ClientCertificateType(input[AUTO]);
+
+ byte tmp[REQUEST_HEADER];
+ input.read(tmp, sizeof(tmp));
+ uint16 sz;
+ ato16(tmp, sz);
+
+ // authorities
+ while (sz) {
+ uint16 dnSz;
+ input.read(tmp, sizeof(tmp));
+ ato16(tmp, dnSz);
+
+ DistinguishedName dn;
+ request.certificate_authorities_.push_back(dn = new (ys)
+ byte[REQUEST_HEADER + dnSz]);
+ memcpy(dn, tmp, REQUEST_HEADER);
+ input.read(&dn[REQUEST_HEADER], dnSz);
+
+ sz -= dnSz + REQUEST_HEADER;
+ }
+
+ return input;
+}
+
+
+// output operator for CertificateRequest
+output_buffer& operator<<(output_buffer& output,
+ const CertificateRequest& request)
+{
+ // types
+ output[AUTO] = request.typeTotal_;
+ for (int i = 0; i < request.typeTotal_; i++)
+ output[AUTO] = request.certificate_types_[i];
+
+ // authorities
+ opaque tmp[REQUEST_HEADER];
+ c16toa(request.get_length() - SIZEOF_ENUM -
+ request.typeTotal_ - REQUEST_HEADER, tmp);
+ output.write(tmp, sizeof(tmp));
+
+ mySTL::list<DistinguishedName>::const_iterator first =
+ request.certificate_authorities_.begin();
+ mySTL::list<DistinguishedName>::const_iterator last =
+ request.certificate_authorities_.end();
+ while (first != last) {
+ uint16 sz;
+ ato16(*first, sz);
+ output.write(*first, sz + REQUEST_HEADER);
+
+ ++first;
+ }
+
+ return output;
+}
+
+
+// CertificateRequest processing handler
+void CertificateRequest::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useCrypto().use_certManager().setSendVerify();
+}
+
+
+HandShakeType CertificateRequest::get_type() const
+{
+ return certificate_request;
+}
+
+
+// CertificateVerify
+CertificateVerify::CertificateVerify() : signature_(0)
+{}
+
+
+CertificateVerify::~CertificateVerify()
+{
+ delete[] signature_;
+}
+
+
+void CertificateVerify::Build(SSL& ssl)
+{
+ build_certHashes(ssl, hashes_);
+
+ uint16 sz = 0;
+ byte len[VERIFY_HEADER];
+ mySTL::auto_ptr<byte> sig;
+
+ // sign
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ if (cert.get_keyType() == rsa_sa_algo) {
+ RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+
+ sz = rsa.get_cipherLength() + VERIFY_HEADER;
+ sig.reset(new (ys) byte[sz]);
+
+ c16toa(sz - VERIFY_HEADER, len);
+ memcpy(sig.get(), len, VERIFY_HEADER);
+ rsa.sign(sig.get() + VERIFY_HEADER, hashes_.md5_, sizeof(Hashes),
+ ssl.getCrypto().get_random());
+ }
+ else { // DSA
+ DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+
+ sz = DSS_SIG_SZ + DSS_ENCODED_EXTRA + VERIFY_HEADER;
+ sig.reset(new (ys) byte[sz]);
+
+ c16toa(sz - VERIFY_HEADER, len);
+ memcpy(sig.get(), len, VERIFY_HEADER);
+ dss.sign(sig.get() + VERIFY_HEADER, hashes_.sha_, SHA_LEN,
+ ssl.getCrypto().get_random());
+
+ byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA];
+ TaoCrypt::EncodeDSA_Signature(sig.get() + VERIFY_HEADER, encoded);
+ memcpy(sig.get() + VERIFY_HEADER, encoded, sizeof(encoded));
+ }
+ set_length(sz);
+ signature_ = sig.release();
+}
+
+
+input_buffer& CertificateVerify::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& CertificateVerify::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for CertificateVerify
+input_buffer& operator>>(input_buffer& input, CertificateVerify& request)
+{
+ byte tmp[VERIFY_HEADER];
+ input.read(tmp, sizeof(tmp));
+
+ uint16 sz = 0;
+ ato16(tmp, sz);
+ request.set_length(sz);
+
+ request.signature_ = new (ys) byte[sz];
+ input.read(request.signature_, sz);
+
+ return input;
+}
+
+
+// output operator for CertificateVerify
+output_buffer& operator<<(output_buffer& output,
+ const CertificateVerify& verify)
+{
+ output.write(verify.signature_, verify.get_length());
+
+ return output;
+}
+
+
+// CertificateVerify processing handler
+void CertificateVerify::Process(input_buffer&, SSL& ssl)
+{
+ const Hashes& hashVerify = ssl.getHashes().get_certVerify();
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (cert.get_peerKeyType() == rsa_sa_algo) {
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+
+ if (!rsa.verify(hashVerify.md5_, sizeof(hashVerify), signature_,
+ get_length()))
+ ssl.SetError(verify_error);
+ }
+ else { // DSA
+ byte decodedSig[DSS_SIG_SZ];
+ TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, get_length());
+
+ DSS dss(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!dss.verify(hashVerify.sha_, SHA_LEN, decodedSig, get_length()))
+ ssl.SetError(verify_error);
+ }
+}
+
+
+HandShakeType CertificateVerify::get_type() const
+{
+ return certificate_verify;
+}
+
+
+// output operator for ClientKeyExchange
+output_buffer& operator<<(output_buffer& output, const ClientKeyExchange& ck)
+{
+ output.write(ck.getKey(), ck.getKeyLength());
+ return output;
+}
+
+
+// Client Key Exchange processing handler
+void ClientKeyExchange::Process(input_buffer& input, SSL& ssl)
+{
+ createKey(ssl);
+ if (ssl.GetError()) return;
+ client_key_->read(ssl, input);
+
+ if (ssl.getCrypto().get_certManager().verifyPeer())
+ build_certHashes(ssl, ssl.useHashes().use_certVerify());
+
+ ssl.useStates().useServer() = clientKeyExchangeComplete;
+}
+
+
+ClientKeyExchange::ClientKeyExchange(SSL& ssl)
+{
+ createKey(ssl);
+}
+
+
+ClientKeyExchange::ClientKeyExchange()
+ : client_key_(0)
+{}
+
+
+ClientKeyExchange::~ClientKeyExchange()
+{
+ delete client_key_;
+}
+
+
+void ClientKeyExchange::build(SSL& ssl)
+{
+ client_key_->build(ssl);
+ set_length(client_key_->get_length());
+}
+
+const opaque* ClientKeyExchange::getKey() const
+{
+ return client_key_->get_clientKey();
+}
+
+
+int ClientKeyExchange::getKeyLength() const
+{
+ return client_key_->get_length();
+}
+
+
+input_buffer& ClientKeyExchange::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& ClientKeyExchange::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ClientKeyExchange::get_type() const
+{
+ return client_key_exchange;
+}
+
+
+// input operator for Finished
+input_buffer& operator>>(input_buffer& input, Finished&)
+{
+ /* do in process */
+
+ return input;
+}
+
+// output operator for Finished
+output_buffer& operator<<(output_buffer& output, const Finished& fin)
+{
+ if (fin.get_length() == FINISHED_SZ) {
+ output.write(fin.hashes_.md5_, MD5_LEN);
+ output.write(fin.hashes_.sha_, SHA_LEN);
+ }
+ else // TLS_FINISHED_SZ
+ output.write(fin.hashes_.md5_, TLS_FINISHED_SZ);
+
+ return output;
+}
+
+
+// Finished processing handler
+void Finished::Process(input_buffer& input, SSL& ssl)
+{
+ // verify hashes
+ const Finished& verify = ssl.getHashes().get_verify();
+ uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
+
+ input.read(hashes_.md5_, finishedSz);
+
+ if (memcmp(&hashes_, &verify.hashes_, finishedSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+
+ // read verify mac
+ opaque verifyMAC[SHA_LEN];
+ uint macSz = finishedSz + HANDSHAKE_HEADER;
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verifyMAC, input.get_buffer() + input.get_current()
+ - macSz, macSz, handshake, true);
+ else
+ hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() - macSz,
+ macSz, handshake, true);
+
+ // read mac and fill
+ opaque mac[SHA_LEN]; // max size
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ input.read(mac, digestSz);
+
+ opaque fill;
+ int padSz = ssl.getSecurity().get_parms().encrypt_size_ -
+ HANDSHAKE_HEADER - finishedSz - digestSz;
+ for (int i = 0; i < padSz; i++)
+ fill = input[AUTO];
+
+ // verify mac
+ if (memcmp(mac, verifyMAC, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+
+ // update states
+ ssl.useStates().useHandShake() = handShakeReady;
+ if (ssl.getSecurity().get_parms().entity_ == client_end)
+ ssl.useStates().useClient() = serverFinishedComplete;
+ else
+ ssl.useStates().useServer() = clientFinishedComplete;
+}
+
+
+Finished::Finished()
+{
+ set_length(FINISHED_SZ);
+}
+
+
+uint8* Finished::set_md5()
+{
+ return hashes_.md5_;
+}
+
+
+uint8* Finished::set_sha()
+{
+ return hashes_.sha_;
+}
+
+
+input_buffer& Finished::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& Finished::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType Finished::get_type() const
+{
+ return finished;
+}
+
+
+void clean(volatile opaque* p, uint sz, RandomPool& ran)
+{
+ uint i(0);
+
+ for (i = 0; i < sz; ++i)
+ p[i] = 0;
+
+ ran.Fill(const_cast<opaque*>(p), sz);
+
+ for (i = 0; i < sz; ++i)
+ p[i] = 0;
+}
+
+
+
+Connection::Connection(ProtocolVersion v, RandomPool& ran)
+ : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0),
+ pre_secret_len_(0), send_server_key_(false), master_clean_(false),
+ TLS_(v.major_ >= 3 && v.minor_ >= 1), version_(v), random_(ran)
+{}
+
+
+Connection::~Connection()
+{
+ CleanMaster(); CleanPreMaster(); delete[] pre_master_secret_;
+}
+
+
+void Connection::AllocPreSecret(uint sz)
+{
+ pre_master_secret_ = new (ys) opaque[pre_secret_len_ = sz];
+}
+
+
+void Connection::TurnOffTLS()
+{
+ TLS_ = false;
+ version_.minor_ = 0;
+}
+
+
+// wipeout master secret
+void Connection::CleanMaster()
+{
+ if (!master_clean_) {
+ volatile opaque* p = master_secret_;
+ clean(p, SECRET_LEN, random_);
+ master_clean_ = true;
+ }
+}
+
+
+// wipeout pre master secret
+void Connection::CleanPreMaster()
+{
+ if (pre_master_secret_) {
+ volatile opaque* p = pre_master_secret_;
+ clean(p, pre_secret_len_, random_);
+
+ delete[] pre_master_secret_;
+ pre_master_secret_ = 0;
+ }
+}
+
+
+// Create functions for message factory
+Message* CreateCipherSpec() { return new (ys) ChangeCipherSpec; }
+Message* CreateAlert() { return new (ys) Alert; }
+Message* CreateHandShake() { return new (ys) HandShakeHeader; }
+Message* CreateData() { return new (ys) Data; }
+
+// Create functions for handshake factory
+HandShakeBase* CreateHelloRequest() { return new (ys) HelloRequest; }
+HandShakeBase* CreateClientHello() { return new (ys) ClientHello; }
+HandShakeBase* CreateServerHello() { return new (ys) ServerHello; }
+HandShakeBase* CreateCertificate() { return new (ys) Certificate; }
+HandShakeBase* CreateServerKeyExchange() { return new (ys) ServerKeyExchange;}
+HandShakeBase* CreateCertificateRequest() { return new (ys)
+ CertificateRequest; }
+HandShakeBase* CreateServerHelloDone() { return new (ys) ServerHelloDone; }
+HandShakeBase* CreateCertificateVerify() { return new (ys) CertificateVerify;}
+HandShakeBase* CreateClientKeyExchange() { return new (ys) ClientKeyExchange;}
+HandShakeBase* CreateFinished() { return new (ys) Finished; }
+
+// Create functions for server key exchange factory
+ServerKeyBase* CreateRSAServerKEA() { return new (ys) RSA_Server; }
+ServerKeyBase* CreateDHServerKEA() { return new (ys) DH_Server; }
+ServerKeyBase* CreateFortezzaServerKEA() { return new (ys) Fortezza_Server; }
+
+// Create functions for client key exchange factory
+ClientKeyBase* CreateRSAClient() { return new (ys)
+ EncryptedPreMasterSecret; }
+ClientKeyBase* CreateDHClient() { return new (ys)
+ ClientDiffieHellmanPublic; }
+ClientKeyBase* CreateFortezzaClient() { return new (ys) FortezzaKeys; }
+
+
+// Constructor calls this to Register compile time callbacks
+void InitMessageFactory(MessageFactory& mf)
+{
+ mf.Reserve(4);
+ mf.Register(alert, CreateAlert);
+ mf.Register(change_cipher_spec, CreateCipherSpec);
+ mf.Register(handshake, CreateHandShake);
+ mf.Register(application_data, CreateData);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitHandShakeFactory(HandShakeFactory& hsf)
+{
+ hsf.Reserve(10);
+ hsf.Register(hello_request, CreateHelloRequest);
+ hsf.Register(client_hello, CreateClientHello);
+ hsf.Register(server_hello, CreateServerHello);
+ hsf.Register(certificate, CreateCertificate);
+ hsf.Register(server_key_exchange, CreateServerKeyExchange);
+ hsf.Register(certificate_request, CreateCertificateRequest);
+ hsf.Register(server_hello_done, CreateServerHelloDone);
+ hsf.Register(certificate_verify, CreateCertificateVerify);
+ hsf.Register(client_key_exchange, CreateClientKeyExchange);
+ hsf.Register(finished, CreateFinished);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitServerKeyFactory(ServerKeyFactory& skf)
+{
+ skf.Reserve(3);
+ skf.Register(rsa_kea, CreateRSAServerKEA);
+ skf.Register(diffie_hellman_kea, CreateDHServerKEA);
+ skf.Register(fortezza_kea, CreateFortezzaServerKEA);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitClientKeyFactory(ClientKeyFactory& ckf)
+{
+ ckf.Reserve(3);
+ ckf.Register(rsa_kea, CreateRSAClient);
+ ckf.Register(diffie_hellman_kea, CreateDHClient);
+ ckf.Register(fortezza_kea, CreateFortezzaClient);
+}
+
+} // namespace
+
+#ifdef __GNUC__
+namespace mySTL {
+template class mySTL::list<unsigned char*>;
+template yaSSL::del_ptr_zero mySTL::for_each(mySTL::list<unsigned char*>::iterator, mySTL::list<unsigned char*>::iterator, yaSSL::del_ptr_zero);
+template mySTL::pair<int, yaSSL::Message* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
+template mySTL::pair<int, yaSSL::HandShakeBase* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
+template void mySTL::destroy<mySTL::pair<int, yaSSL::Message* (*)()>*>(mySTL::pair<int, yaSSL::Message* (*)()>*, mySTL::pair<int, yaSSL::Message* (*)()>*);
+template void mySTL::destroy<mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*>(mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*, mySTL::pair<int, yaSSL::HandShakeBase* (*)()>*);
+template mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
+template void mySTL::destroy<mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ServerKeyBase* (*)()>*);
+template mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>* mySTL::uninit_copy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
+template class mySTL::list<TaoCrypt::Signer*>;
+template class mySTL::list<yaSSL::SSL_SESSION*>;
+template class mySTL::list<yaSSL::input_buffer*>;
+template class mySTL::list<yaSSL::output_buffer*>;
+template class mySTL::list<yaSSL::x509*>;
+template void mySTL::destroy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*);
+template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<TaoCrypt::Signer*>::iterator, mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero);
+template yaSSL::del_ptr_zero mySTL::for_each<mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::x509*>::iterator, mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero);
+}
+#endif
+
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
new file mode 100644
index 00000000000..c552cfa7189
--- /dev/null
+++ b/extra/yassl/src/yassl_int.cpp
@@ -0,0 +1,1976 @@
+/* yassl_int.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL internal source implements SSL supporting types not specified in the
+ * draft along with type conversion functions.
+ */
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+#include "timer.hpp"
+#include "openssl/ssl.h" // for DH
+
+
+void* operator new(size_t sz, yaSSL::new_t)
+{
+ void* ptr = ::operator new(sz);
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+void* operator new[](size_t sz, yaSSL::new_t n)
+{
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ void* ptr = ::operator new(sz); // no ::operator new[]
+#else
+ void* ptr = ::operator new[](sz);
+#endif
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+
+namespace yaSSL {
+
+
+using mySTL::min;
+
+
+new_t ys; // for library new
+
+
+// convert a 32 bit integer into a 24 bit one
+void c32to24(uint32 u32, uint24& u24)
+{
+ u24[0] = (u32 >> 16) & 0xff;
+ u24[1] = (u32 >> 8) & 0xff;
+ u24[2] = u32 & 0xff;
+}
+
+
+// convert a 24 bit integer into a 32 bit one
+void c24to32(const uint24 u24, uint32& u32)
+{
+ u32 = 0;
+ u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
+}
+
+
+// convert with return for ease of use
+uint32 c24to32(const uint24 u24)
+{
+ uint32 ret;
+ c24to32(u24, ret);
+
+ return ret;
+}
+
+
+// using a for opaque since underlying type is unsgined char and o is not a
+// good leading identifier
+
+// convert opaque to 16 bit integer
+void ato16(const opaque* c, uint16& u16)
+{
+ u16 = 0;
+ u16 = (c[0] << 8) | (c[1]);
+}
+
+
+// convert (copy) opaque to 24 bit integer
+void ato24(const opaque* c, uint24& u24)
+{
+ u24[0] = c[0];
+ u24[1] = c[1];
+ u24[2] = c[2];
+}
+
+
+// convert 16 bit integer to opaque
+void c16toa(uint16 u16, opaque* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+// convert 24 bit integer to opaque
+void c24toa(const uint24 u24, opaque* c)
+{
+ c[0] = u24[0];
+ c[1] = u24[1];
+ c[2] = u24[2];
+}
+
+
+// convert 32 bit integer to opaque
+void c32toa(uint32 u32, opaque* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+States::States() : recordLayer_(recordReady), handshakeLayer_(preHandshake),
+ clientState_(serverNull), serverState_(clientNull),
+ what_(no_error) {}
+
+const RecordLayerState& States::getRecord() const
+{
+ return recordLayer_;
+}
+
+
+const HandShakeState& States::getHandShake() const
+{
+ return handshakeLayer_;
+}
+
+
+const ClientState& States::getClient() const
+{
+ return clientState_;
+}
+
+
+const ServerState& States::getServer() const
+{
+ return serverState_;
+}
+
+
+const char* States::getString() const
+{
+ return errorString_;
+}
+
+
+YasslError States::What() const
+{
+ return what_;
+}
+
+
+RecordLayerState& States::useRecord()
+{
+ return recordLayer_;
+}
+
+
+HandShakeState& States::useHandShake()
+{
+ return handshakeLayer_;
+}
+
+
+ClientState& States::useClient()
+{
+ return clientState_;
+}
+
+
+ServerState& States::useServer()
+{
+ return serverState_;
+}
+
+
+char* States::useString()
+{
+ return errorString_;
+}
+
+
+void States::SetError(YasslError ye)
+{
+ what_ = ye;
+}
+
+
+sslFactory::sslFactory() :
+ messageFactory_(InitMessageFactory),
+ handShakeFactory_(InitHandShakeFactory),
+ serverKeyFactory_(InitServerKeyFactory),
+ clientKeyFactory_(InitClientKeyFactory)
+{}
+
+
+const MessageFactory& sslFactory::getMessage() const
+{
+ return messageFactory_;
+}
+
+
+const HandShakeFactory& sslFactory::getHandShake() const
+{
+ return handShakeFactory_;
+}
+
+
+const ServerKeyFactory& sslFactory::getServerKey() const
+{
+ return serverKeyFactory_;
+}
+
+
+const ClientKeyFactory& sslFactory::getClientKey() const
+{
+ return clientKeyFactory_;
+}
+
+
+// extract context parameters and store
+SSL::SSL(SSL_CTX* ctx)
+ : secure_(ctx->getMethod()->getVersion(), crypto_.use_random(),
+ ctx->getMethod()->getSide(), ctx->GetCiphers(), ctx)
+{
+ if (int err = crypto_.get_random().GetError()) {
+ SetError(YasslError(err));
+ return;
+ }
+
+ CertManager& cm = crypto_.use_certManager();
+ cm.CopySelfCert(ctx->getCert());
+
+ bool serverSide = secure_.use_parms().entity_ == server_end;
+
+ if (ctx->getKey()) {
+ if (int err = cm.SetPrivateKey(*ctx->getKey())) {
+ SetError(YasslError(err));
+ return;
+ }
+ }
+ else if (serverSide) {
+ SetError(no_key_file);
+ return;
+ }
+
+ if (ctx->getMethod()->verifyPeer())
+ cm.setVerifyPeer();
+ if (ctx->getMethod()->failNoCert())
+ cm.setFailNoCert();
+
+ if (serverSide)
+ crypto_.SetDH(ctx->GetDH_Parms());
+
+ const SSL_CTX::CertList& ca = ctx->GetCA_List();
+ SSL_CTX::CertList::const_iterator first(ca.begin());
+ SSL_CTX::CertList::const_iterator last(ca.end());
+
+ while (first != last) {
+ if (int err = cm.CopyCaCert(*first)) {
+ SetError(YasslError(err));
+ return;
+ }
+ ++first;
+ }
+}
+
+
+// store pending security parameters from Server Hello
+void SSL::set_pending(Cipher suite)
+{
+ Parameters& parms = secure_.use_parms();
+
+ switch (suite) {
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_256_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_128_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_3DES_EDE_CBC_SHA]
+ , MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_RC4_128_SHA:
+ parms.bulk_cipher_algorithm_ = rc4;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = RC4_KEY_SZ;
+ parms.iv_size_ = 0;
+ parms.cipher_type_ = stream;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) RC4);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_RC4_128_MD5:
+ parms.bulk_cipher_algorithm_ = rc4;
+ parms.mac_algorithm_ = md5;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = MD5_LEN;
+ parms.key_size_ = RC4_KEY_SZ;
+ parms.iv_size_ = 0;
+ parms.cipher_type_ = stream;
+ crypto_.setDigest(new (ys) MD5);
+ crypto_.setCipher(new (ys) RC4);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_MD5],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_DHE_RSA_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_DHE_DSS_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_AES_256_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_AES_128_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_3DES_EDE_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ default:
+ SetError(unknown_cipher);
+ }
+}
+
+
+// store peer's random
+void SSL::set_random(const opaque* random, ConnectionEnd sender)
+{
+ if (sender == client_end)
+ memcpy(secure_.use_connection().client_random_, random, RAN_LEN);
+ else
+ memcpy(secure_.use_connection().server_random_, random, RAN_LEN);
+}
+
+
+// store client pre master secret
+void SSL::set_preMaster(const opaque* pre, uint sz)
+{
+ secure_.use_connection().AllocPreSecret(sz);
+ memcpy(secure_.use_connection().pre_master_secret_, pre, sz);
+}
+
+
+// store master secret
+void SSL::set_masterSecret(const opaque* sec)
+{
+ memcpy(secure_.use_connection().master_secret_, sec, SECRET_LEN);
+}
+
+// store server issued id
+void SSL::set_sessionID(const opaque* sessionID)
+{
+ memcpy(secure_.use_connection().sessionID_, sessionID, ID_LEN);
+}
+
+
+// store error
+void SSL::SetError(YasslError ye)
+{
+ states_.SetError(ye);
+ //strncpy(states_.useString(), e.what(), mySTL::named_exception::NAME_SIZE);
+ // TODO: add string here
+}
+
+
+// locals
+namespace {
+
+// DeriveKeys and MasterSecret helper sets prefix letters
+static bool setPrefix(opaque* sha_input, int i)
+{
+ switch (i) {
+ case 0:
+ memcpy(sha_input, "A", 1);
+ break;
+ case 1:
+ memcpy(sha_input, "BB", 2);
+ break;
+ case 2:
+ memcpy(sha_input, "CCC", 3);
+ break;
+ case 3:
+ memcpy(sha_input, "DDDD", 4);
+ break;
+ case 4:
+ memcpy(sha_input, "EEEEE", 5);
+ break;
+ case 5:
+ memcpy(sha_input, "FFFFFF", 6);
+ break;
+ case 6:
+ memcpy(sha_input, "GGGGGGG", 7);
+ break;
+ default:
+ return false; // prefix_error
+ }
+ return true;
+}
+
+
+const char handshake_order[] = "Out of order HandShake Message!";
+
+
+} // namespcae for locals
+
+
+void SSL::order_error()
+{
+ SetError(out_of_order);
+}
+
+
+// Create and store the master secret see page 32, 6.1
+void SSL::makeMasterSecret()
+{
+ if (isTLS())
+ makeTLSMasterSecret();
+ else {
+ opaque sha_output[SHA_LEN];
+
+ const uint& preSz = secure_.get_connection().pre_secret_len_;
+ output_buffer md5_input(preSz + SHA_LEN);
+ output_buffer sha_input(PREFIX + preSz + 2 * RAN_LEN);
+
+ MD5 md5;
+ SHA sha;
+
+ md5_input.write(secure_.get_connection().pre_master_secret_, preSz);
+
+ for (int i = 0; i < MASTER_ROUNDS; ++i) {
+ opaque prefix[PREFIX];
+ if (!setPrefix(prefix, i)) {
+ SetError(prefix_error);
+ return;
+ }
+
+ sha_input.set_current(0);
+ sha_input.write(prefix, i + 1);
+
+ sha_input.write(secure_.get_connection().pre_master_secret_,preSz);
+ sha_input.write(secure_.get_connection().client_random_, RAN_LEN);
+ sha_input.write(secure_.get_connection().server_random_, RAN_LEN);
+ sha.get_digest(sha_output, sha_input.get_buffer(),
+ sha_input.get_size());
+
+ md5_input.set_current(preSz);
+ md5_input.write(sha_output, SHA_LEN);
+ md5.get_digest(&secure_.use_connection().master_secret_[i*MD5_LEN],
+ md5_input.get_buffer(), md5_input.get_size());
+ }
+ deriveKeys();
+ }
+ secure_.use_connection().CleanPreMaster();
+}
+
+
+// create TLSv1 master secret
+void SSL::makeTLSMasterSecret()
+{
+ opaque seed[SEED_LEN];
+
+ memcpy(seed, secure_.get_connection().client_random_, RAN_LEN);
+ memcpy(&seed[RAN_LEN], secure_.get_connection().server_random_, RAN_LEN);
+
+ PRF(secure_.use_connection().master_secret_, SECRET_LEN,
+ secure_.get_connection().pre_master_secret_,
+ secure_.get_connection().pre_secret_len_,
+ master_label, MASTER_LABEL_SZ,
+ seed, SEED_LEN);
+
+ deriveTLSKeys();
+}
+
+
+// derive mac, write, and iv keys for server and client, see page 34, 6.2.2
+void SSL::deriveKeys()
+{
+ int length = 2 * secure_.get_parms().hash_size_ +
+ 2 * secure_.get_parms().key_size_ +
+ 2 * secure_.get_parms().iv_size_;
+ int rounds = length / MD5_LEN + ((length % MD5_LEN) ? 1 : 0);
+ input_buffer key_data(rounds * MD5_LEN);
+
+ opaque sha_output[SHA_LEN];
+ opaque md5_input[SECRET_LEN + SHA_LEN];
+ opaque sha_input[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+
+ MD5 md5;
+ SHA sha;
+
+ memcpy(md5_input, secure_.get_connection().master_secret_, SECRET_LEN);
+
+ for (int i = 0; i < rounds; ++i) {
+ int j = i + 1;
+ if (!setPrefix(sha_input, i)) {
+ SetError(prefix_error);
+ return;
+ }
+
+ memcpy(&sha_input[j], secure_.get_connection().master_secret_,
+ SECRET_LEN);
+ memcpy(&sha_input[j+SECRET_LEN],
+ secure_.get_connection().server_random_, RAN_LEN);
+ memcpy(&sha_input[j + SECRET_LEN + RAN_LEN],
+ secure_.get_connection().client_random_, RAN_LEN);
+ sha.get_digest(sha_output, sha_input,
+ sizeof(sha_input) - KEY_PREFIX + j);
+
+ memcpy(&md5_input[SECRET_LEN], sha_output, SHA_LEN);
+ md5.get_digest(key_data.get_buffer() + i * MD5_LEN,
+ md5_input, sizeof(md5_input));
+ }
+ storeKeys(key_data.get_buffer());
+}
+
+
+// derive mac, write, and iv keys for server and client
+void SSL::deriveTLSKeys()
+{
+ int length = 2 * secure_.get_parms().hash_size_ +
+ 2 * secure_.get_parms().key_size_ +
+ 2 * secure_.get_parms().iv_size_;
+ opaque seed[SEED_LEN];
+ input_buffer key_data(length);
+
+ memcpy(seed, secure_.get_connection().server_random_, RAN_LEN);
+ memcpy(&seed[RAN_LEN], secure_.get_connection().client_random_, RAN_LEN);
+
+ PRF(key_data.get_buffer(), length, secure_.get_connection().master_secret_,
+ SECRET_LEN, key_label, KEY_LABEL_SZ, seed, SEED_LEN);
+
+ storeKeys(key_data.get_buffer());
+}
+
+
+// store mac, write, and iv keys for client and server
+void SSL::storeKeys(const opaque* key_data)
+{
+ int sz = secure_.get_parms().hash_size_;
+ memcpy(secure_.use_connection().client_write_MAC_secret_, key_data, sz);
+ int i = sz;
+ memcpy(secure_.use_connection().server_write_MAC_secret_,&key_data[i], sz);
+ i += sz;
+
+ sz = secure_.get_parms().key_size_;
+ memcpy(secure_.use_connection().client_write_key_, &key_data[i], sz);
+ i += sz;
+ memcpy(secure_.use_connection().server_write_key_, &key_data[i], sz);
+ i += sz;
+
+ sz = secure_.get_parms().iv_size_;
+ memcpy(secure_.use_connection().client_write_IV_, &key_data[i], sz);
+ i += sz;
+ memcpy(secure_.use_connection().server_write_IV_, &key_data[i], sz);
+
+ setKeys();
+}
+
+
+// set encrypt/decrypt keys and ivs
+void SSL::setKeys()
+{
+ Connection& conn = secure_.use_connection();
+
+ if (secure_.get_parms().entity_ == client_end) {
+ crypto_.use_cipher().set_encryptKey(conn.client_write_key_,
+ conn.client_write_IV_);
+ crypto_.use_cipher().set_decryptKey(conn.server_write_key_,
+ conn.server_write_IV_);
+ }
+ else {
+ crypto_.use_cipher().set_encryptKey(conn.server_write_key_,
+ conn.server_write_IV_);
+ crypto_.use_cipher().set_decryptKey(conn.client_write_key_,
+ conn.client_write_IV_);
+ }
+}
+
+
+
+// local functors
+namespace yassl_int_cpp_local1 {
+
+struct SumData {
+ uint total_;
+ SumData() : total_(0) {}
+ void operator()(input_buffer* data) { total_ += data->get_remaining(); }
+};
+
+
+struct SumBuffer {
+ uint total_;
+ SumBuffer() : total_(0) {}
+ void operator()(output_buffer* buffer) { total_ += buffer->get_size(); }
+};
+
+} // namespace for locals
+using namespace yassl_int_cpp_local1;
+
+uint SSL::bufferedData()
+{
+ return mySTL::for_each(buffers_.getData().begin(),buffers_.getData().end(),
+ SumData()).total_;
+}
+
+// use input buffer to fill data
+void SSL::fillData(Data& data)
+{
+ if (GetError()) return;
+ uint dataSz = data.get_length(); // input, data size to fill
+ uint elements = buffers_.getData().size();
+
+ data.set_length(0); // output, actual data filled
+ dataSz = min(dataSz, bufferedData());
+
+ for (uint i = 0; i < elements; i++) {
+ input_buffer* front = buffers_.getData().front();
+ uint frontSz = front->get_remaining();
+ uint readSz = min(dataSz - data.get_length(), frontSz);
+
+ front->read(data.set_buffer() + data.get_length(), readSz);
+ data.set_length(data.get_length() + readSz);
+
+ if (readSz == frontSz) {
+ buffers_.useData().pop_front();
+ delete front;
+ }
+ if (data.get_length() == dataSz)
+ break;
+ }
+}
+
+
+// flush output buffer
+void SSL::flushBuffer()
+{
+ if (GetError()) return;
+
+ uint sz = mySTL::for_each(buffers_.getHandShake().begin(),
+ buffers_.getHandShake().end(),
+ SumBuffer()).total_;
+ output_buffer out(sz);
+ uint elements = buffers_.getHandShake().size();
+
+ for (uint i = 0; i < elements; i++) {
+ output_buffer* front = buffers_.getHandShake().front();
+ out.write(front->get_buffer(), front->get_size());
+
+ buffers_.useHandShake().pop_front();
+ delete front;
+ }
+ Send(out.get_buffer(), out.get_size());
+}
+
+
+void SSL::Send(const byte* buffer, uint sz)
+{
+ if (socket_.send(buffer, sz) != sz)
+ SetError(send_error);
+}
+
+
+// get sequence number, if verify get peer's
+uint SSL::get_SEQIncrement(bool verify)
+{
+ if (verify)
+ return secure_.use_connection().peer_sequence_number_++;
+ else
+ return secure_.use_connection().sequence_number_++;
+}
+
+
+const byte* SSL::get_macSecret(bool verify)
+{
+ if ( (secure_.get_parms().entity_ == client_end && !verify) ||
+ (secure_.get_parms().entity_ == server_end && verify) )
+ return secure_.get_connection().client_write_MAC_secret_;
+ else
+ return secure_.get_connection().server_write_MAC_secret_;
+}
+
+
+void SSL::verifyState(const RecordLayerHeader& rlHeader)
+{
+ if (GetError()) return;
+
+ if (states_.getRecord() == recordNotReady ||
+ (rlHeader.type_ == application_data && // data and handshake
+ states_.getHandShake() != handShakeReady) ) // isn't complete yet
+ SetError(record_layer);
+}
+
+
+void SSL::verifyState(const HandShakeHeader& hsHeader)
+{
+ if (GetError()) return;
+
+ if (states_.getHandShake() == handShakeNotReady) {
+ SetError(handshake_layer);
+ return;
+ }
+
+ if (secure_.get_parms().entity_ == client_end)
+ verifyClientState(hsHeader.get_handshakeType());
+ else
+ verifyServerState(hsHeader.get_handshakeType());
+}
+
+
+void SSL::verifyState(ClientState cs)
+{
+ if (GetError()) return;
+ if (states_.getClient() != cs) order_error();
+}
+
+
+void SSL::verifyState(ServerState ss)
+{
+ if (GetError()) return;
+ if (states_.getServer() != ss) order_error();
+}
+
+
+void SSL::verfiyHandShakeComplete()
+{
+ if (GetError()) return;
+ if (states_.getHandShake() != handShakeReady) order_error();
+}
+
+
+void SSL::verifyClientState(HandShakeType hsType)
+{
+ if (GetError()) return;
+
+ switch(hsType) {
+ case server_hello :
+ if (states_.getClient() != serverNull)
+ order_error();
+ break;
+ case certificate :
+ if (states_.getClient() != serverHelloComplete)
+ order_error();
+ break;
+ case server_key_exchange :
+ if (states_.getClient() != serverCertComplete)
+ order_error();
+ break;
+ case certificate_request :
+ if (states_.getClient() != serverCertComplete &&
+ states_.getClient() != serverKeyExchangeComplete)
+ order_error();
+ break;
+ case server_hello_done :
+ if (states_.getClient() != serverCertComplete &&
+ states_.getClient() != serverKeyExchangeComplete)
+ order_error();
+ break;
+ case finished :
+ if (states_.getClient() != serverHelloDoneComplete ||
+ secure_.get_parms().pending_) // no change
+ order_error(); // cipher yet
+ break;
+ default :
+ order_error();
+ };
+}
+
+
+void SSL::verifyServerState(HandShakeType hsType)
+{
+ if (GetError()) return;
+
+ switch(hsType) {
+ case client_hello :
+ if (states_.getServer() != clientNull)
+ order_error();
+ break;
+ case certificate :
+ if (states_.getServer() != clientHelloComplete)
+ order_error();
+ break;
+ case client_key_exchange :
+ if (states_.getServer() != clientHelloComplete)
+ order_error();
+ break;
+ case certificate_verify :
+ if (states_.getServer() != clientKeyExchangeComplete)
+ order_error();
+ break;
+ case finished :
+ if (states_.getServer() != clientKeyExchangeComplete ||
+ secure_.get_parms().pending_) // no change
+ order_error(); // cipher yet
+ break;
+ default :
+ order_error();
+ };
+}
+
+
+// try to find a suite match
+void SSL::matchSuite(const opaque* peer, uint length)
+{
+ if (length == 0 || (length % 2) != 0) {
+ SetError(bad_input);
+ return;
+ }
+
+ // start with best, if a match we are good, Ciphers are at odd index
+ // since all SSL and TLS ciphers have 0x00 first byte
+ for (uint i = 1; i < secure_.get_parms().suites_size_; i += 2)
+ for (uint j = 1; j < length; j+= 2)
+ if (secure_.use_parms().suites_[i] == peer[j]) {
+ secure_.use_parms().suite_[0] = 0x00;
+ secure_.use_parms().suite_[1] = peer[j];
+ return;
+ }
+
+ SetError(match_error);
+}
+
+
+void SSL::set_session(SSL_SESSION* s)
+{
+ if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume()))
+ secure_.set_resuming(true);
+}
+
+
+const Crypto& SSL::getCrypto() const
+{
+ return crypto_;
+}
+
+
+const Security& SSL::getSecurity() const
+{
+ return secure_;
+}
+
+
+const States& SSL::getStates() const
+{
+ return states_;
+}
+
+
+const sslHashes& SSL::getHashes() const
+{
+ return hashes_;
+}
+
+
+const sslFactory& SSL::getFactory() const
+{
+ return GetSSL_Factory();
+}
+
+
+const Socket& SSL::getSocket() const
+{
+ return socket_;
+}
+
+
+YasslError SSL::GetError() const
+{
+ return states_.What();
+}
+
+
+Crypto& SSL::useCrypto()
+{
+ return crypto_;
+}
+
+
+Security& SSL::useSecurity()
+{
+ return secure_;
+}
+
+
+States& SSL::useStates()
+{
+ return states_;
+}
+
+
+sslHashes& SSL::useHashes()
+{
+ return hashes_;
+}
+
+
+Socket& SSL::useSocket()
+{
+ return socket_;
+}
+
+
+Log& SSL::useLog()
+{
+ return log_;
+}
+
+
+bool SSL::isTLS() const
+{
+ return secure_.get_connection().TLS_;
+}
+
+
+void SSL::addData(input_buffer* data)
+{
+ buffers_.useData().push_back(data);
+}
+
+
+void SSL::addBuffer(output_buffer* b)
+{
+ buffers_.useHandShake().push_back(b);
+}
+
+
+// store connection parameters
+SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran)
+ : timeout_(DEFAULT_TIMEOUT), random_(ran)
+{
+ const Connection& conn = ssl.getSecurity().get_connection();
+
+ memcpy(sessionID_, conn.sessionID_, ID_LEN);
+ memcpy(master_secret_, conn.master_secret_, SECRET_LEN);
+ memcpy(suite_, ssl.getSecurity().get_parms().suite_, SUITE_LEN);
+
+ bornOn_ = lowResTimer();
+}
+
+
+// for resumption copy in ssl::parameters
+SSL_SESSION::SSL_SESSION(RandomPool& ran)
+ : bornOn_(0), timeout_(0), random_(ran)
+{
+ memset(sessionID_, 0, ID_LEN);
+ memset(master_secret_, 0, SECRET_LEN);
+ memset(suite_, 0, SUITE_LEN);
+}
+
+
+SSL_SESSION& SSL_SESSION::operator=(const SSL_SESSION& that)
+{
+ memcpy(sessionID_, that.sessionID_, ID_LEN);
+ memcpy(master_secret_, that.master_secret_, SECRET_LEN);
+ memcpy(suite_, that.suite_, SUITE_LEN);
+
+ bornOn_ = that.bornOn_;
+ timeout_ = that.timeout_;
+
+ return *this;
+}
+
+
+const opaque* SSL_SESSION::GetID() const
+{
+ return sessionID_;
+}
+
+
+const opaque* SSL_SESSION::GetSecret() const
+{
+ return master_secret_;
+}
+
+
+const Cipher* SSL_SESSION::GetSuite() const
+{
+ return suite_;
+}
+
+
+uint SSL_SESSION::GetBornOn() const
+{
+ return bornOn_;
+}
+
+
+uint SSL_SESSION::GetTimeOut() const
+{
+ return timeout_;
+}
+
+
+void SSL_SESSION::SetTimeOut(uint t)
+{
+ timeout_ = t;
+}
+
+
+extern void clean(volatile opaque*, uint, RandomPool&);
+
+
+// clean up secret data
+SSL_SESSION::~SSL_SESSION()
+{
+ volatile opaque* p = master_secret_;
+ clean(p, SECRET_LEN, random_);
+}
+
+
+Sessions Sessions::instance; // simple singleton
+
+Sessions& GetSessions()
+{
+ return Sessions::instance;
+}
+
+sslFactory sslFactory::instance;
+
+sslFactory& GetSSL_Factory()
+{
+ return sslFactory::instance;
+}
+
+
+typedef Mutex::Lock Lock;
+
+
+void Sessions::add(const SSL& ssl)
+{
+ Lock guard(mutex_);
+ list_.push_back(new (ys) SSL_SESSION(ssl, random_));
+}
+
+
+Sessions::~Sessions()
+{
+ mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero());
+}
+
+
+namespace yassl_int_cpp_local2 { // locals
+
+typedef mySTL::list<SSL_SESSION*>::iterator iterator;
+
+struct sess_match {
+ const opaque* id_;
+ explicit sess_match(const opaque* p) : id_(p) {}
+
+ bool operator()(SSL_SESSION* sess)
+ {
+ if ( memcmp(sess->GetID(), id_, ID_LEN) == 0)
+ return true;
+ return false;
+ }
+};
+
+
+} // local namespace
+using namespace yassl_int_cpp_local2;
+
+// lookup session by id, return a copy if space provided
+SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy)
+{
+ Lock guard(mutex_);
+ iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id));
+
+ if (find != list_.end()) {
+ uint current = lowResTimer();
+ if ( ((*find)->GetBornOn() + (*find)->GetTimeOut()) < current) {
+ del_ptr_zero()(*find);
+ list_.erase(find);
+ return 0;
+ }
+ if (copy)
+ *copy = *(*find);
+ return *find;
+ }
+ return 0;
+}
+
+
+// remove a session by id
+void Sessions::remove(const opaque* id)
+{
+ Lock guard(mutex_);
+ iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id));
+
+ if (find != list_.end()) {
+ del_ptr_zero()(*find);
+ list_.erase(find);
+ }
+}
+
+
+SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv)
+ : version_(pv), side_(ce), verifyPeer_(false), failNoCert_(false)
+{}
+
+
+ProtocolVersion SSL_METHOD::getVersion() const
+{
+ return version_;
+}
+
+
+ConnectionEnd SSL_METHOD::getSide() const
+{
+ return side_;
+}
+
+
+void SSL_METHOD::setVerifyPeer()
+{
+ verifyPeer_ = true;
+}
+
+
+void SSL_METHOD::setFailNoCert()
+{
+ failNoCert_ = true;
+}
+
+
+bool SSL_METHOD::verifyPeer() const
+{
+ return verifyPeer_;
+}
+
+
+bool SSL_METHOD::failNoCert() const
+{
+ return failNoCert_;
+}
+
+
+SSL_CTX::SSL_CTX(SSL_METHOD* meth)
+ : method_(meth), certificate_(0), privateKey_(0)
+{}
+
+
+SSL_CTX::~SSL_CTX()
+{
+ delete method_;
+ delete certificate_;
+ delete privateKey_;
+
+ mySTL::for_each(caList_.begin(), caList_.end(), del_ptr_zero());
+}
+
+
+void SSL_CTX::AddCA(x509* ca)
+{
+ caList_.push_back(ca);
+}
+
+
+const SSL_CTX::CertList&
+SSL_CTX::GetCA_List() const
+{
+ return caList_;
+}
+
+
+const x509* SSL_CTX::getCert() const
+{
+ return certificate_;
+}
+
+
+const x509* SSL_CTX::getKey() const
+{
+ return privateKey_;
+}
+
+
+const SSL_METHOD* SSL_CTX::getMethod() const
+{
+ return method_;
+}
+
+
+const Ciphers& SSL_CTX::GetCiphers() const
+{
+ return ciphers_;
+}
+
+
+const DH_Parms& SSL_CTX::GetDH_Parms() const
+{
+ return dhParms_;
+}
+
+
+const Stats& SSL_CTX::GetStats() const
+{
+ return stats_;
+}
+
+
+void SSL_CTX::setVerifyPeer()
+{
+ method_->setVerifyPeer();
+}
+
+
+void SSL_CTX::setFailNoCert()
+{
+ method_->setFailNoCert();
+}
+
+
+bool SSL_CTX::SetDH(const DH& dh)
+{
+ dhParms_.p_ = dh.p->int_;
+ dhParms_.g_ = dh.g->int_;
+
+ return dhParms_.set_ = true;
+}
+
+
+bool SSL_CTX::SetCipherList(const char* list)
+{
+ if (!list)
+ return false;
+
+ bool ret = false;
+ char name[MAX_SUITE_NAME];
+
+ char needle[] = ":";
+ char* haystack = const_cast<char*>(list);
+ char* prev;
+
+ const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
+ int idx = 0;
+
+ for(;;) {
+ int len;
+ prev = haystack;
+ haystack = strstr(haystack, needle);
+
+ if (!haystack) // last cipher
+ len = min(sizeof(name), strlen(prev));
+ else
+ len = min(sizeof(name), (size_t)(haystack - prev));
+
+ strncpy(name, prev, len);
+ name[(len == sizeof(name)) ? len - 1 : len] = 0;
+
+ for (int i = 0; i < suiteSz; i++)
+ if (strncmp(name, cipher_names[i], sizeof(name)) == 0) {
+
+ ciphers_.suites_[idx++] = 0x00; // first byte always zero
+ ciphers_.suites_[idx++] = i;
+
+ if (!ret) ret = true; // found at least one
+ break;
+ }
+ if (!haystack) break;
+ haystack++;
+ }
+
+ if (ret) {
+ ciphers_.setSuites_ = true;
+ ciphers_.suiteSz_ = idx;
+ }
+
+ return ret;
+}
+
+
+void SSL_CTX::IncrementStats(StatsField fd)
+{
+
+ Lock guard(mutex_);
+
+ switch (fd) {
+
+ case Accept:
+ ++stats_.accept_;
+ break;
+
+ case Connect:
+ ++stats_.connect_;
+ break;
+
+ case AcceptGood:
+ ++stats_.acceptGood_;
+ break;
+
+ case ConnectGood:
+ ++stats_.connectGood_;
+ break;
+
+ case AcceptRenegotiate:
+ ++stats_.acceptRenegotiate_;
+ break;
+
+ case ConnectRenegotiate:
+ ++stats_.connectRenegotiate_;
+ break;
+
+ case Hits:
+ ++stats_.hits_;
+ break;
+
+ case CbHits:
+ ++stats_.cbHits_;
+ break;
+
+ case CacheFull:
+ ++stats_.cacheFull_;
+ break;
+
+ case Misses:
+ ++stats_.misses_;
+ break;
+
+ case Timeouts:
+ ++stats_.timeouts_;
+ break;
+
+ case Number:
+ ++stats_.number_;
+ break;
+
+ case GetCacheSize:
+ ++stats_.getCacheSize_;
+ break;
+
+ case VerifyMode:
+ ++stats_.verifyMode_;
+ break;
+
+ case VerifyDepth:
+ ++stats_.verifyDepth_;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+Crypto::Crypto()
+ : digest_(0), cipher_(0), dh_(0)
+{}
+
+
+Crypto::~Crypto()
+{
+ delete dh_;
+ delete cipher_;
+ delete digest_;
+}
+
+
+const Digest& Crypto::get_digest() const
+{
+ return *digest_;
+}
+
+
+const BulkCipher& Crypto::get_cipher() const
+{
+ return *cipher_;
+}
+
+
+const DiffieHellman& Crypto::get_dh() const
+{
+ return *dh_;
+}
+
+
+const RandomPool& Crypto::get_random() const
+{
+ return random_;
+}
+
+
+const CertManager& Crypto::get_certManager() const
+{
+ return cert_;
+}
+
+
+
+Digest& Crypto::use_digest()
+{
+ return *digest_;
+}
+
+
+BulkCipher& Crypto::use_cipher()
+{
+ return *cipher_;
+}
+
+
+DiffieHellman& Crypto::use_dh()
+{
+ return *dh_;
+}
+
+
+RandomPool& Crypto::use_random()
+{
+ return random_;
+}
+
+
+CertManager& Crypto::use_certManager()
+{
+ return cert_;
+}
+
+
+
+void Crypto::SetDH(DiffieHellman* dh)
+{
+ dh_ = dh;
+}
+
+
+void Crypto::SetDH(const DH_Parms& dh)
+{
+ if (dh.set_)
+ dh_ = new (ys) DiffieHellman(dh.p_, dh.g_, random_);
+}
+
+
+bool Crypto::DhSet()
+{
+ return dh_ != 0;
+}
+
+
+void Crypto::setDigest(Digest* digest)
+{
+ digest_ = digest;
+}
+
+
+void Crypto::setCipher(BulkCipher* c)
+{
+ cipher_ = c;
+}
+
+
+const MD5& sslHashes::get_MD5() const
+{
+ return md5HandShake_;
+}
+
+
+const SHA& sslHashes::get_SHA() const
+{
+ return shaHandShake_;
+}
+
+
+const Finished& sslHashes::get_verify() const
+{
+ return verify_;
+}
+
+
+const Hashes& sslHashes::get_certVerify() const
+{
+ return certVerify_;
+}
+
+
+MD5& sslHashes::use_MD5(){
+ return md5HandShake_;
+}
+
+
+SHA& sslHashes::use_SHA()
+{
+ return shaHandShake_;
+}
+
+
+Finished& sslHashes::use_verify()
+{
+ return verify_;
+}
+
+
+Hashes& sslHashes::use_certVerify()
+{
+ return certVerify_;
+}
+
+
+Buffers::~Buffers()
+{
+ mySTL::for_each(handShakeList_.begin(), handShakeList_.end(),
+ del_ptr_zero()) ;
+ mySTL::for_each(dataList_.begin(), dataList_.end(),
+ del_ptr_zero()) ;
+}
+
+
+const Buffers::inputList& Buffers::getData() const
+{
+ return dataList_;
+}
+
+
+const Buffers::outputList& Buffers::getHandShake() const
+{
+ return handShakeList_;
+}
+
+
+Buffers::inputList& Buffers::useData()
+{
+ return dataList_;
+}
+
+
+Buffers::outputList& Buffers::useHandShake()
+{
+ return handShakeList_;
+}
+
+
+Security::Security(ProtocolVersion pv, RandomPool& ran, ConnectionEnd ce,
+ const Ciphers& ciphers, SSL_CTX* ctx)
+ : conn_(pv, ran), parms_(ce, ciphers, pv), resumeSession_(ran), ctx_(ctx),
+ resuming_(false)
+{}
+
+
+const Connection& Security::get_connection() const
+{
+ return conn_;
+}
+
+
+const SSL_CTX* Security::GetContext() const
+{
+ return ctx_;
+}
+
+
+const Parameters& Security::get_parms() const
+{
+ return parms_;
+}
+
+
+const SSL_SESSION& Security::get_resume() const
+{
+ return resumeSession_;
+}
+
+
+bool Security::get_resuming() const
+{
+ return resuming_;
+}
+
+
+Connection& Security::use_connection()
+{
+ return conn_;
+}
+
+
+Parameters& Security::use_parms()
+{
+ return parms_;
+}
+
+
+SSL_SESSION& Security::use_resume()
+{
+ return resumeSession_;
+}
+
+
+void Security::set_resuming(bool b)
+{
+ resuming_ = b;
+}
+
+
+X509_NAME::X509_NAME(const char* n, size_t sz)
+ : name_(0)
+{
+ if (sz) {
+ name_ = new (ys) char[sz];
+ memcpy(name_, n, sz);
+ }
+}
+
+
+X509_NAME::~X509_NAME()
+{
+ delete[] name_;
+}
+
+
+char* X509_NAME::GetName()
+{
+ return name_;
+}
+
+
+X509::X509(const char* i, size_t iSz, const char* s, size_t sSz)
+ : issuer_(i, iSz), subject_(s, sSz)
+{}
+
+
+X509_NAME* X509::GetIssuer()
+{
+ return &issuer_;
+}
+
+
+X509_NAME* X509::GetSubject()
+{
+ return &subject_;
+}
+
+} // namespace
+
+#ifdef __GNUC__
+namespace mySTL {
+template yaSSL::yassl_int_cpp_local1::SumData mySTL::for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData);
+template yaSSL::yassl_int_cpp_local1::SumBuffer mySTL::for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer);
+template mySTL::list<yaSSL::SSL_SESSION*>::iterator mySTL::find_if<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::yassl_int_cpp_local2::sess_match);
+}
+#endif
diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am
new file mode 100644
index 00000000000..af3ded7abfd
--- /dev/null
+++ b/extra/yassl/taocrypt/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = src
+EXTRA_DIST = taocrypt.dsw taocrypt.dsp
diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp
new file mode 100644
index 00000000000..b2c93eff9fe
--- /dev/null
+++ b/extra/yassl/taocrypt/include/aes.hpp
@@ -0,0 +1,89 @@
+/* aes.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* aes.hpp defines AES
+*/
+
+
+#ifndef TAO_CRYPT_AES_HPP
+#define TAO_CRYPT_AES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "modes.hpp"
+#include "block.hpp"
+
+namespace TaoCrypt {
+
+enum { AES_BLOCK_SIZE = 16 };
+
+
+// AES encryption and decryption, see FIPS-197
+class AES : public Mode_BASE<AES_BLOCK_SIZE> {
+public:
+ enum { BLOCK_SIZE = AES_BLOCK_SIZE };
+
+ AES(CipherDir DIR, Mode MODE) : dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte* iv, word32 sz, CipherDir fake = ENCRYPTION);
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ CipherDir dir_;
+ Mode mode_;
+
+ static const word32 Te0[256];
+ static const word32 Te1[256];
+ static const word32 Te2[256];
+ static const word32 Te3[256];
+ static const word32 Te4[256];
+
+ static const word32 Td0[256];
+ static const word32 Td1[256];
+ static const word32 Td2[256];
+ static const word32 Td3[256];
+ static const word32 Td4[256];
+
+ static const word32 rcon_[];
+
+ word32 rounds_;
+ Word32Block key_;
+
+ void encrypt(const byte*, const byte*, byte*) const;
+ void decrypt(const byte*, const byte*, byte*) const;
+
+ AES(const AES&); // hide copy
+ AES& operator=(const AES&); // and assign
+};
+
+
+typedef BlockCipher<ENCRYPTION, AES, ECB> AES_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, AES, ECB> AES_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, AES, CBC> AES_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, AES, CBC> AES_CBC_Decryption;
+
+
+
+} // naemspace
+
+#endif // TAO_CRYPT_AES_HPP
diff --git a/extra/yassl/taocrypt/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp
new file mode 100644
index 00000000000..74f244507f6
--- /dev/null
+++ b/extra/yassl/taocrypt/include/algebra.hpp
@@ -0,0 +1,316 @@
+/* algebra.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's algebra.h from CryptoPP */
+
+#ifndef TAO_CRYPT_ALGEBRA_HPP
+#define TAO_CRYPT_ALGEBRA_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+class Integer;
+
+// "const Element&" returned by member functions are references
+// to internal data members. Since each object may have only
+// one such data member for holding results, the following code
+// will produce incorrect results:
+// abcd = group.Add(group.Add(a,b), group.Add(c,d));
+// But this should be fine:
+// abcd = group.Add(a, group.Add(b, group.Add(c,d));
+
+//! Abstract Group
+template <class T> class TAOCRYPT_NO_VTABLE AbstractGroup
+{
+public:
+ typedef T Element;
+
+ virtual ~AbstractGroup() {}
+
+ virtual bool Equal(const Element &a, const Element &b) const =0;
+ virtual const Element& Identity() const =0;
+ virtual const Element& Add(const Element &a, const Element &b) const =0;
+ virtual const Element& Inverse(const Element &a) const =0;
+ virtual bool InversionIsFast() const {return false;}
+
+ virtual const Element& Double(const Element &a) const;
+ virtual const Element& Subtract(const Element &a, const Element &b) const;
+ virtual Element& Accumulate(Element &a, const Element &b) const;
+ virtual Element& Reduce(Element &a, const Element &b) const;
+
+ virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
+ virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousMultiply(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const;
+};
+
+//! Abstract Ring
+template <class T> class TAOCRYPT_NO_VTABLE AbstractRing
+ : public AbstractGroup<T>
+{
+public:
+ typedef T Element;
+
+ AbstractRing() {m_mg.m_pRing = this;}
+ AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
+ AbstractRing& operator=(const AbstractRing &source) {return *this;}
+
+ virtual bool IsUnit(const Element &a) const =0;
+ virtual const Element& MultiplicativeIdentity() const =0;
+ virtual const Element& Multiply(const Element&, const Element&) const =0;
+ virtual const Element& MultiplicativeInverse(const Element &a) const =0;
+
+ virtual const Element& Square(const Element &a) const;
+ virtual const Element& Divide(const Element &a, const Element &b) const;
+
+ virtual Element Exponentiate(const Element &a, const Integer &e) const;
+ virtual Element CascadeExponentiate(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousExponentiate(Element *results, const Element&,
+ const Integer *exponents, unsigned int exponentsCount) const;
+
+ virtual const AbstractGroup<T>& MultiplicativeGroup() const
+ {return m_mg;}
+
+private:
+ class MultiplicativeGroupT : public AbstractGroup<T>
+ {
+ public:
+ const AbstractRing<T>& GetRing() const
+ {return *m_pRing;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return GetRing().Equal(a, b);}
+
+ const Element& Identity() const
+ {return GetRing().MultiplicativeIdentity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return GetRing().Multiply(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a = GetRing().Multiply(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return GetRing().MultiplicativeInverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return GetRing().Divide(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a = GetRing().Divide(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return GetRing().Square(a);}
+
+ Element ScalarMultiply(const Element &a, const Integer &e) const
+ {return GetRing().Exponentiate(a, e);}
+
+ Element CascadeScalarMultiply(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const
+ {return GetRing().CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousMultiply(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const
+ {GetRing().SimultaneousExponentiate(results, base, exponents,
+ exponentsCount);}
+
+ const AbstractRing<T> *m_pRing;
+ };
+
+ MultiplicativeGroupT m_mg;
+};
+
+// ********************************************************
+
+//! Base and Exponent
+template <class T, class E = Integer>
+struct BaseAndExponent
+{
+public:
+ BaseAndExponent() {}
+ BaseAndExponent(const T &base, const E &exponent) : base(base),
+ exponent(exponent) {}
+ bool operator<(const BaseAndExponent<T, E> &rhs) const
+ {return exponent < rhs.exponent;}
+ T base;
+ E exponent;
+};
+
+// VC60 workaround: incomplete member template support
+template <class Element, class Iterator>
+ Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group,
+ Iterator begin, Iterator end);
+template <class Element, class Iterator>
+ Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring,
+ Iterator begin, Iterator end);
+
+// ********************************************************
+
+//! Abstract Euclidean Domain
+template <class T> class TAOCRYPT_NO_VTABLE AbstractEuclideanDomain
+ : public AbstractRing<T>
+{
+public:
+ typedef T Element;
+
+ virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a,
+ const Element &d) const =0;
+
+ virtual const Element& Mod(const Element &a, const Element &b) const =0;
+ virtual const Element& Gcd(const Element &a, const Element &b) const;
+
+protected:
+ mutable Element result;
+};
+
+// ********************************************************
+
+//! EuclideanDomainOf
+template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
+{
+public:
+ typedef T Element;
+
+ EuclideanDomainOf() {}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return a==b;}
+
+ const Element& Identity() const
+ {return Element::Zero();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return result = a+b;}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a+=b;}
+
+ const Element& Inverse(const Element &a) const
+ {return result = -a;}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return result = a-b;}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a-=b;}
+
+ const Element& Double(const Element &a) const
+ {return result = a.Doubled();}
+
+ const Element& MultiplicativeIdentity() const
+ {return Element::One();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return result = a*b;}
+
+ const Element& Square(const Element &a) const
+ {return result = a.Squared();}
+
+ bool IsUnit(const Element &a) const
+ {return a.IsUnit();}
+
+ const Element& MultiplicativeInverse(const Element &a) const
+ {return result = a.MultiplicativeInverse();}
+
+ const Element& Divide(const Element &a, const Element &b) const
+ {return result = a/b;}
+
+ const Element& Mod(const Element &a, const Element &b) const
+ {return result = a%b;}
+
+ void DivisionAlgorithm(Element &r, Element &q, const Element &a,
+ const Element &d) const
+ {Element::Divide(r, q, a, d);}
+
+private:
+ mutable Element result;
+};
+
+//! Quotient Ring
+template<class T> class QuotientRing : public AbstractRing<typename T::Element>
+{
+public:
+ typedef T EuclideanDomain;
+ typedef typename T::Element Element;
+
+ QuotientRing(const EuclideanDomain &domain, const Element &modulus)
+ : m_domain(domain), m_modulus(modulus) {}
+
+ const EuclideanDomain & GetDomain() const
+ {return m_domain;}
+
+ const Element& GetModulus() const
+ {return m_modulus;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b),
+ m_modulus), m_domain.Identity());}
+
+ const Element& Identity() const
+ {return m_domain.Identity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return m_domain.Add(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return m_domain.Accumulate(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return m_domain.Inverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return m_domain.Subtract(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return m_domain.Reduce(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return m_domain.Double(a);}
+
+ bool IsUnit(const Element &a) const
+ {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
+
+ const Element& MultiplicativeIdentity() const
+ {return m_domain.MultiplicativeIdentity();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
+
+ const Element& Square(const Element &a) const
+ {return m_domain.Mod(m_domain.Square(a), m_modulus);}
+
+ const Element& MultiplicativeInverse(const Element &a) const;
+
+protected:
+ EuclideanDomain m_domain;
+ Element m_modulus;
+};
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ALGEBRA_HPP
diff --git a/extra/yassl/taocrypt/include/arc4.hpp b/extra/yassl/taocrypt/include/arc4.hpp
new file mode 100644
index 00000000000..c919c8ea2ae
--- /dev/null
+++ b/extra/yassl/taocrypt/include/arc4.hpp
@@ -0,0 +1,59 @@
+/* arc4.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* arc4.hpp defines ARC4
+*/
+
+
+#ifndef TAO_CRYPT_ARC4_HPP
+#define TAO_CRYPT_ARC4_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+// ARC4 encryption and decryption
+class ARC4 {
+public:
+ enum { STATE_SIZE = 256 };
+
+ typedef ARC4 Encryption;
+ typedef ARC4 Decryption;
+
+ ARC4() {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte*, word32);
+private:
+ byte x_;
+ byte y_;
+ byte state_[STATE_SIZE];
+
+ ARC4(const ARC4&); // hide copy
+ const ARC4 operator=(const ARC4&); // and assign
+};
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ARC4_HPP
+
diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp
new file mode 100644
index 00000000000..71633339a40
--- /dev/null
+++ b/extra/yassl/taocrypt/include/asn.hpp
@@ -0,0 +1,327 @@
+/* asn.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* asn.hpp provides ASN1 BER, PublicKey, and x509v3 decoding
+*/
+
+
+#ifndef TAO_CRYPT_ASN_HPP
+#define TAO_CRYPT_ASN_HPP
+
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "list.hpp"
+#include "error.hpp"
+
+
+
+namespace TaoCrypt {
+
+// these tags and flags are not complete
+enum ASNTag
+{
+ BOOLEAN = 0x01,
+ INTEGER = 0x02,
+ BIT_STRING = 0x03,
+ OCTET_STRING = 0x04,
+ TAG_NULL = 0x05,
+ OBJECT_IDENTIFIER = 0x06,
+ OBJECT_DESCRIPTOR = 0x07,
+ EXTERNAL = 0x08,
+ REAL = 0x09,
+ ENUMERATED = 0x0a,
+ UTF8_STRING = 0x0c,
+ SEQUENCE = 0x10,
+ SET = 0x11,
+ NUMERIC_STRING = 0x12,
+ PRINTABLE_STRING = 0x13,
+ T61_STRING = 0x14,
+ VIDEOTEXT_STRING = 0x15,
+ IA5_STRING = 0x16,
+ UTC_TIME = 0x17,
+ GENERALIZED_TIME = 0x18,
+ GRAPHIC_STRING = 0x19,
+ VISIBLE_STRING = 0x1a,
+ GENERAL_STRING = 0x1b,
+ LONG_LENGTH = 0x80
+};
+
+enum ASNIdFlag
+{
+ UNIVERSAL = 0x00,
+ DATA = 0x01,
+ HEADER = 0x02,
+ CONSTRUCTED = 0x20,
+ APPLICATION = 0x40,
+ CONTEXT_SPECIFIC = 0x80,
+ PRIVATE = 0xc0
+};
+
+
+enum DNTags
+{
+ COMMON_NAME = 0x03,
+};
+
+
+enum Constants
+{
+ MIN_DATE_SZ = 13,
+ MAX_DATE_SZ = 15,
+ MAX_ALGO_SZ = 16,
+ MAX_LENGTH_SZ = 5,
+ MAX_SEQ_SZ = 5, // enum(seq|con) + length(4)
+ MAX_ALGO_SIZE = 9,
+ MAX_DIGEST_SZ = 25, // SHA + enum(Bit or Octet) + length(4)
+ DSA_SIG_SZ = 40,
+};
+
+
+class Source;
+class RSA_PublicKey;
+class RSA_PrivateKey;
+class DSA_PublicKey;
+class DSA_PrivateKey;
+class Integer;
+class DH;
+
+
+// General BER decoding
+class BER_Decoder {
+protected:
+ Source& source_;
+public:
+ explicit BER_Decoder(Source& s) : source_(s) {}
+ virtual ~BER_Decoder() {}
+
+ Integer& GetInteger(Integer&);
+ word32 GetSequence();
+ word32 GetSet();
+ word32 GetVersion();
+ word32 GetExplicitVersion();
+
+ Error GetError();
+private:
+ virtual void ReadHeader() = 0;
+
+ BER_Decoder(const BER_Decoder&); // hide copy
+ BER_Decoder& operator=(const BER_Decoder&); // and assign
+};
+
+
+// RSA Private Key BER Decoder
+class RSA_Private_Decoder : public BER_Decoder {
+public:
+ explicit RSA_Private_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(RSA_PrivateKey&);
+private:
+ void ReadHeader();
+};
+
+
+// RSA Public Key BER Decoder
+class RSA_Public_Decoder : public BER_Decoder {
+public:
+ explicit RSA_Public_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(RSA_PublicKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DSA Private Key BER Decoder
+class DSA_Private_Decoder : public BER_Decoder {
+public:
+ explicit DSA_Private_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DSA_PrivateKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DSA Public Key BER Decoder
+class DSA_Public_Decoder : public BER_Decoder {
+public:
+ explicit DSA_Public_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DSA_PublicKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DH Key BER Decoder
+class DH_Decoder : public BER_Decoder {
+public:
+ explicit DH_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DH&);
+private:
+ void ReadHeader();
+};
+
+
+// General PublicKey
+class PublicKey {
+ byte* key_;
+ word32 sz_;
+public:
+ explicit PublicKey(const byte* k = 0, word32 s = 0);
+ ~PublicKey() { delete[] key_; }
+
+ const byte* GetKey() const { return key_; }
+ word32 size() const { return sz_; }
+
+ void SetKey(const byte*);
+ void SetSize(word32 s);
+
+ void AddToEnd(const byte*, word32);
+private:
+ PublicKey(const PublicKey&); // hide copy
+ PublicKey& operator=(const PublicKey&); // and assign
+};
+
+
+enum { SHA_SIZE = 20 };
+
+
+// A Signing Authority
+class Signer {
+ PublicKey key_;
+ char* name_;
+ byte hash_[SHA_SIZE];
+public:
+ Signer(const byte* k, word32 kSz, const char* n, const byte* h);
+ ~Signer();
+
+ const PublicKey& GetPublicKey() const { return key_; }
+ const char* GetCommonName() const { return name_; }
+ const byte* GetHash() const { return hash_; }
+
+private:
+ Signer(const Signer&); // hide copy
+ Signer& operator=(const Signer&); // and assign
+};
+
+
+typedef mySTL::list<Signer*> SignerList;
+
+
+enum SigType { SHAwDSA = 517, MD2wRSA = 646, MD5wRSA = 648, SHAwRSA =649};
+enum HashType { MD2h = 646, MD5h = 649, SHAh = 88 };
+enum KeyType { DSAk = 515, RSAk = 645 }; // sums of algo OID
+
+
+// an x509v Certificate BER Decoder
+class CertDecoder : public BER_Decoder {
+public:
+ explicit CertDecoder(Source&, bool decode = true, SignerList* = 0);
+ ~CertDecoder();
+
+ const PublicKey& GetPublicKey() const { return key_; }
+ KeyType GetKeyType() const { return KeyType(keyOID_); }
+ const char* GetIssuer() const { return issuer_; }
+ const char* GetCommonName() const { return subject_; }
+ const byte* GetHash() const { return subjectHash_; }
+
+ void DecodeToKey();
+
+ enum DateType { BEFORE, AFTER };
+ enum NameType { ISSUER, SUBJECT };
+private:
+ PublicKey key_;
+ word32 certBegin_; // offset to start of cert
+ word32 sigIndex_; // offset to start of signature
+ word32 sigLength_; // length of signature
+ word32 signatureOID_; // sum of algorithm object id
+ word32 keyOID_; // sum of key algo object id
+ byte subjectHash_[SHA_SIZE]; // hash of all Names
+ byte issuerHash_[SHA_SIZE]; // hash of all Names
+ byte* signature_;
+ char* issuer_; // CommonName
+ char* subject_; // CommonName
+
+ void ReadHeader();
+ void Decode(SignerList*);
+ void StoreKey();
+ void AddDSA();
+ bool ValidateSelfSignature();
+ bool ValidateSignature(SignerList*);
+ bool ConfirmSignature(Source&);
+ void GetKey();
+ void GetName(NameType);
+ void GetValidity();
+ void GetDate(DateType);
+ void GetCompareHash(const byte*, word32, byte*, word32);
+ word32 GetAlgoId();
+ word32 GetSignature();
+ word32 GetDigest();
+};
+
+
+word32 GetLength(Source&);
+
+word32 SetLength(word32, byte*);
+word32 SetSequence(word32, byte*);
+
+word32 EncodeDSA_Signature(const byte* signature, byte* output);
+word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output);
+word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz);
+
+
+// General DER encoding
+class DER_Encoder {
+public:
+ DER_Encoder() {}
+ virtual ~DER_Encoder() {}
+
+ word32 SetAlgoID(HashType, byte*);
+
+ Error GetError() const { return error_; }
+private:
+ //virtual void WriteHeader() = 0;
+ Error error_;
+
+ DER_Encoder(const DER_Encoder&); // hide copy
+ DER_Encoder& operator=(const DER_Encoder&); // and assign
+};
+
+
+
+class Signature_Encoder : public DER_Encoder {
+ const byte* digest_;
+ word32 digestSz_;
+ SigType digestOID_;
+public:
+ explicit Signature_Encoder(const byte*, word32, HashType, Source&);
+
+private:
+ void WriteHeader();
+ word32 SetDigest(const byte*, word32, byte*);
+
+ Signature_Encoder(const Signature_Encoder&); // hide copy
+ Signature_Encoder& operator=(const Signature_Encoder&); // and assign
+};
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ASN_HPP
diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp
new file mode 100644
index 00000000000..6e96ec9cc35
--- /dev/null
+++ b/extra/yassl/taocrypt/include/block.hpp
@@ -0,0 +1,211 @@
+/* block.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* block.hpp provides word and byte blocks with configurable allocators
+*/
+
+
+#ifndef TAO_CRYPT_BLOCK_HPP
+#define TAO_CRYPT_BLOCK_HPP
+
+#include "algorithm.hpp" // mySTL::swap
+#include "stdexcept.hpp" // mySTL::runtime_error
+#include "misc.hpp"
+#include <string.h> // memcpy
+#include <cstddef> // ptrdiff_t
+
+
+#if defined(_MSC_VER) && defined(_CRTAPI1)
+#define TAOCRYPT_MSVCRT6
+#endif
+
+
+namespace TaoCrypt {
+
+
+// a Base class for Allocators
+template<class T>
+class AllocatorBase
+{
+public:
+ typedef T value_type;
+ typedef size_t size_type;
+#ifdef TAOCRYPT_MSVCRT6
+ typedef ptrdiff_t difference_type;
+#else
+ typedef std::ptrdiff_t difference_type;
+#endif
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+
+ pointer address(reference r) const {return (&r);}
+ const_pointer address(const_reference r) const {return (&r); }
+ void construct(pointer p, const T& val) {new (p) T(val);}
+ void destroy(pointer p) {p->~T();}
+ size_type max_size() const {return ~size_type(0)/sizeof(T);}
+protected:
+ static void CheckSize(size_t n)
+ {
+ assert(n <= ~size_t(0) / sizeof(T));
+ }
+};
+
+
+// General purpose realloc
+template<typename T, class A>
+typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize,
+ typename A::size_type newSize, bool preserve)
+{
+ if (oldSize == newSize)
+ return p;
+
+ if (preserve) {
+ A b = A();
+ typename A::pointer newPointer = b.allocate(newSize, 0);
+ memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize));
+ a.deallocate(p, oldSize);
+ mySTL::swap(a, b);
+ return newPointer;
+ }
+ else {
+ a.deallocate(p, oldSize);
+ return a.allocate(newSize, 0);
+ }
+}
+
+
+// Allocator that zeros out memory on deletion
+template <class T>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ typedef typename AllocatorBase<T>::pointer pointer;
+ typedef typename AllocatorBase<T>::size_type size_type;
+
+ pointer allocate(size_type n, const void* = 0)
+ {
+ CheckSize(n);
+ if (n == 0)
+ return 0;
+ return new (tc) T[n];
+ }
+
+ void deallocate(void* p, size_type n)
+ {
+ memset(p, 0, n * sizeof(T));
+ delete [] (T*)p;
+ }
+
+ pointer reallocate(T* p, size_type oldSize, size_type newSize,
+ bool preserve)
+ {
+ return StdReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ // VS.NET STL enforces the policy of "All STL-compliant allocators have to
+ // provide a template class member called rebind".
+ template <class U> struct rebind { typedef AllocatorWithCleanup<U> other;};
+};
+
+
+// Block class template
+template<typename T, class A = AllocatorWithCleanup<T> >
+class Block {
+public:
+ explicit Block(word32 s = 0) : sz_(s), buffer_(allocator_.allocate(sz_))
+ { CleanNew(sz_); }
+
+ Block(const T* buff, word32 s) : sz_(s), buffer_(allocator_.allocate(sz_))
+ { memcpy(buffer_, buff, sz_ * sizeof(T)); }
+
+ Block(const Block& that) : sz_(that.sz_), buffer_(allocator_.allocate(sz_))
+ { memcpy(buffer_, that.buffer_, sz_ * sizeof(T)); }
+
+ Block& operator=(const Block& that) {
+ Block tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ T& operator[] (word32 i) { assert(i < sz_); return buffer_[i]; }
+ const T& operator[] (word32 i) const
+ { assert(i < sz_); return buffer_[i]; }
+
+ T* operator+ (word32 i) { return buffer_ + i; }
+ const T* operator+ (word32 i) const { return buffer_ + i; }
+
+ word32 size() const { return sz_; }
+
+ T* get_buffer() const { return buffer_; }
+ T* begin() const { return get_buffer(); }
+
+ void CleanGrow(word32 newSize)
+ {
+ if (newSize > sz_) {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
+ memset(buffer_ + sz_, 0, (newSize - sz_) * sizeof(T));
+ sz_ = newSize;
+ }
+ }
+
+ void CleanNew(word32 newSize)
+ {
+ New(newSize);
+ memset(buffer_, 0, sz_ * sizeof(T));
+ }
+
+ void New(word32 newSize)
+ {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, false);
+ sz_ = newSize;
+ }
+
+ void resize(word32 newSize)
+ {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
+ sz_ = newSize;
+ }
+
+ void Swap(Block& other) {
+ mySTL::swap(sz_, other.sz_);
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(allocator_, other.allocator_);
+ }
+
+ ~Block() { allocator_.deallocate(buffer_, sz_); }
+private:
+ word32 sz_; // size in Ts
+ T* buffer_;
+ A allocator_;
+};
+
+
+typedef Block<byte> ByteBlock;
+typedef Block<word> WordBlock;
+typedef Block<word32> Word32Block;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_BLOCK_HPP
diff --git a/extra/yassl/taocrypt/include/coding.hpp b/extra/yassl/taocrypt/include/coding.hpp
new file mode 100644
index 00000000000..9aab2a30c7e
--- /dev/null
+++ b/extra/yassl/taocrypt/include/coding.hpp
@@ -0,0 +1,94 @@
+/* coding.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* coding.hpp defines hex and base64 encoding/decoing
+*/
+
+#ifndef TAO_CRYPT_CODING_HPP
+#define TAO_CRYPT_CODING_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+
+namespace TaoCrypt {
+
+class Source;
+
+
+// Hex Encoding, see RFC 3548
+class HexEncoder {
+ ByteBlock encoded_;
+ Source& plain_;
+public:
+ explicit HexEncoder(Source& s) : plain_(s) { Encode(); }
+private:
+ void Encode();
+
+ HexEncoder(const HexEncoder&); // hide copy
+ HexEncoder& operator=(const HexEncoder&); // and assign
+};
+
+
+// Hex Decoding, see RFC 3548
+class HexDecoder {
+ ByteBlock decoded_;
+ Source& coded_;
+public:
+ explicit HexDecoder(Source& s) : coded_(s) { Decode(); }
+private:
+ void Decode();
+
+ HexDecoder(const HexDecoder&); // hide copy
+ HexDecoder& operator=(const HexDecoder&); // and assign
+};
+
+
+// Base 64 encoding, see RFC 3548
+class Base64Encoder {
+ ByteBlock encoded_;
+ Source& plain_;
+public:
+ explicit Base64Encoder(Source& s) : plain_(s) { Encode(); }
+private:
+ void Encode();
+
+ Base64Encoder(const Base64Encoder&); // hide copy
+ Base64Encoder& operator=(const Base64Encoder&); // and assign
+};
+
+
+// Base 64 decoding, see RFC 3548
+class Base64Decoder {
+ ByteBlock decoded_;
+ Source& coded_;
+public:
+ explicit Base64Decoder(Source& s) : coded_(s) { Decode(); }
+private:
+ void Decode();
+
+ Base64Decoder(const Base64Decoder&); // hide copy
+ Base64Decoder& operator=(const Base64Decoder&); // and assign
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_CODING_HPP
diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp
new file mode 100644
index 00000000000..e8100b4e198
--- /dev/null
+++ b/extra/yassl/taocrypt/include/des.hpp
@@ -0,0 +1,121 @@
+/* des.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* des.hpp defines DES, DES_EDE2, and DES_EDE3
+ see FIPS 46-2 and FIPS 81
+*/
+
+
+#ifndef TAO_CRYPT_DES_HPP
+#define TAO_CRYPT_DES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "modes.hpp"
+
+namespace TaoCrypt {
+
+enum { DES_BLOCK_SIZE = 8 };
+
+// Base for all DES types
+class DES_BASE : public Mode_BASE<DES_BLOCK_SIZE> {
+public:
+ enum { BLOCK_SIZE = DES_BLOCK_SIZE, KEY_SIZE = 32, BOXES = 8,
+ BOX_SIZE = 64 };
+
+ DES_BASE(CipherDir DIR, Mode MODE) : dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+protected:
+ CipherDir dir_;
+ Mode mode_;
+private:
+ DES_BASE(const DES_BASE&); // hide copy
+ DES_BASE& operator=(const DES_BASE&); // and assign
+};
+
+
+// DES
+class DES : public DES_BASE {
+public:
+ DES(CipherDir DIR, Mode MODE) : DES_BASE(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void RawProcessBlock(word32&, word32&) const;
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ word32 k_[KEY_SIZE];
+};
+
+
+// DES_EDE2
+class DES_EDE2 : public DES_BASE {
+public:
+ DES_EDE2(CipherDir DIR, Mode MODE)
+ : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ DES des1_;
+ DES des2_;
+};
+
+
+// DES_EDE3
+class DES_EDE3 : public DES_BASE {
+public:
+ DES_EDE3(CipherDir DIR, Mode MODE)
+ : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE),
+ des3_(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ DES des1_;
+ DES des2_;
+ DES des3_;
+};
+
+
+typedef BlockCipher<ENCRYPTION, DES, ECB> DES_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES, ECB> DES_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES, CBC> DES_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES, CBC> DES_CBC_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE2, ECB> DES_EDE2_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE2, ECB> DES_EDE2_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE2, CBC> DES_EDE2_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE2, CBC> DES_EDE2_CBC_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE3, ECB> DES_EDE3_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE3, ECB> DES_EDE3_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE3, CBC> DES_EDE3_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE3, CBC> DES_EDE3_CBC_Decryption;
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_DES_HPP
diff --git a/extra/yassl/taocrypt/include/dh.hpp b/extra/yassl/taocrypt/include/dh.hpp
new file mode 100644
index 00000000000..54a1705546b
--- /dev/null
+++ b/extra/yassl/taocrypt/include/dh.hpp
@@ -0,0 +1,89 @@
+/* dh.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* dh.hpp provides Diffie-Hellman support
+*/
+
+
+#ifndef TAO_CRYPT_DH_HPP
+#define TAO_CRYPT_DH_HPP
+
+#include "misc.hpp"
+#include "integer.hpp"
+
+namespace TaoCrypt {
+
+
+class Source;
+
+
+// Diffie-Hellman
+class DH {
+public:
+ DH() {}
+ DH(Integer& p, Integer& g) : p_(p), g_(g) {}
+ explicit DH(Source&);
+
+ DH(const DH& that) : p_(that.p_), g_(that.g_) {}
+ DH& operator=(const DH& that)
+ {
+ DH tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(DH& other)
+ {
+ p_.Swap(other.p_);
+ g_.Swap(other.g_);
+ }
+
+ void Initialize(Source&);
+ void Initialize(Integer& p, Integer& g)
+ {
+ SetP(p);
+ SetG(g);
+ }
+
+ void GenerateKeyPair(RandomNumberGenerator&, byte*, byte*);
+ void Agree(byte*, const byte*, const byte*);
+
+ void SetP(const Integer& p) { p_ = p; }
+ void SetG(const Integer& g) { g_ = g; }
+
+ Integer& GetP() { return p_; }
+ Integer& GetG() { return g_; }
+
+ // for p and agree
+ word32 GetByteLength() const { return p_.ByteCount(); }
+private:
+ // group parms
+ Integer p_;
+ Integer g_;
+
+ void GeneratePrivate(RandomNumberGenerator&, byte*);
+ void GeneratePublic(const byte*, byte*);
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_DH_HPP
diff --git a/extra/yassl/taocrypt/include/dsa.hpp b/extra/yassl/taocrypt/include/dsa.hpp
new file mode 100644
index 00000000000..f1fdd2dfa25
--- /dev/null
+++ b/extra/yassl/taocrypt/include/dsa.hpp
@@ -0,0 +1,129 @@
+/* dsa.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* dsa.hpp provides Digitial Signautre Algorithm see FIPS 186-2
+*/
+
+#ifndef TAO_CRYPT_DSA_HPP
+#define TAO_CRYPT_DSA_HPP
+
+#include "integer.hpp"
+
+
+namespace TaoCrypt {
+
+class Source;
+
+
+class DSA_PublicKey {
+protected:
+ Integer p_;
+ Integer q_;
+ Integer g_;
+ Integer y_;
+public:
+ DSA_PublicKey() {}
+ explicit DSA_PublicKey(Source&);
+
+ void Initialize(Source&);
+ void Initialize(const Integer& p, const Integer& q, const Integer& g,
+ const Integer& y);
+
+ const Integer& GetModulus() const;
+ const Integer& GetSubGroupOrder() const;
+ const Integer& GetSubGroupGenerator() const;
+ const Integer& GetPublicPart() const;
+
+ void SetModulus(const Integer&);
+ void SetSubGroupOrder(const Integer&);
+ void SetSubGroupGenerator(const Integer&);
+ void SetPublicPart(const Integer&);
+
+ word32 SignatureLength() const;
+
+ DSA_PublicKey(const DSA_PublicKey&);
+ DSA_PublicKey& operator=(const DSA_PublicKey&);
+
+ void Swap(DSA_PublicKey& other);
+};
+
+
+
+class DSA_PrivateKey : public DSA_PublicKey {
+ Integer x_;
+public:
+ DSA_PrivateKey() {}
+ explicit DSA_PrivateKey(Source&);
+
+ void Initialize(Source&);
+ void Initialize(const Integer& p, const Integer& q, const Integer& g,
+ const Integer& y, const Integer& x);
+
+ const Integer& GetPrivatePart() const;
+
+ void SetPrivatePart(const Integer&);
+private:
+ DSA_PrivateKey(const DSA_PrivateKey&); // hide copy
+ DSA_PrivateKey& operator=(const DSA_PrivateKey&); // and assign
+};
+
+
+
+class DSA_Signer {
+ const DSA_PrivateKey& key_;
+ Integer r_;
+ Integer s_;
+public:
+ explicit DSA_Signer(const DSA_PrivateKey&);
+
+ word32 Sign(const byte* sha_digest, byte* sig, RandomNumberGenerator&);
+
+ const Integer& GetR() const;
+ const Integer& GetS() const;
+private:
+ DSA_Signer(const DSA_Signer&); // hide copy
+ DSA_Signer& operator=(DSA_Signer&); // and assign
+};
+
+
+class DSA_Verifier {
+ const DSA_PublicKey& key_;
+ Integer r_;
+ Integer s_;
+public:
+ explicit DSA_Verifier(const DSA_PublicKey&);
+
+ bool Verify(const byte* sha_digest, const byte* sig);
+
+ const Integer& GetR() const;
+ const Integer& GetS() const;
+private:
+ DSA_Verifier(const DSA_Verifier&); // hide copy
+ DSA_Verifier& operator=(const DSA_Verifier&); // and assign
+};
+
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_DSA_HPP
diff --git a/extra/yassl/taocrypt/include/error.hpp b/extra/yassl/taocrypt/include/error.hpp
new file mode 100644
index 00000000000..cb7f82731c7
--- /dev/null
+++ b/extra/yassl/taocrypt/include/error.hpp
@@ -0,0 +1,86 @@
+/* error.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* error.hpp provides a taocrypt error numbers
+ *
+ */
+
+
+#ifndef TAO_CRYPT_ERROR_HPP
+#define TAO_CRYPT_ERROR_HPP
+
+
+namespace TaoCrypt {
+
+
+enum ErrorNumber {
+
+NO_ERROR = 0, // "not in error state"
+
+// RandomNumberGenerator
+WINCRYPT_E = 1001, // "bad wincrypt acquire"
+CRYPTGEN_E = 1002, // "CryptGenRandom error"
+OPEN_RAN_E = 1003, // "open /dev/urandom error"
+READ_RAN_E = 1004, // "read /dev/urandom error"
+
+// Integer
+INTEGER_E = 1010, // "bad DER Integer Header"
+
+
+// ASN.1
+SEQUENCE_E = 1020, // "bad Sequence Header"
+SET_E = 1021, // "bad Set Header"
+VERSION_E = 1022, // "version length not 1"
+SIG_OID_E = 1023, // "signature OID mismatch"
+BIT_STR_E = 1024, // "bad BitString Header"
+UNKNOWN_OID_E = 1025, // "unknown key OID type"
+OBJECT_ID_E = 1026, // "bad Ojbect ID Header"
+TAG_NULL_E = 1027, // "expected TAG NULL"
+EXPECT_0_E = 1028, // "expected 0"
+OCTET_STR_E = 1029, // "bad Octet String Header"
+TIME_E = 1030, // "bad TIME"
+
+DATE_SZ_E = 1031, // "bad Date Size"
+SIG_LEN_E = 1032, // "bad Signature Length"
+UNKOWN_SIG_E = 1033, // "unknown signature OID"
+UNKOWN_HASH_E = 1034, // "unknown hash OID"
+DSA_SZ_E = 1035, // "bad DSA r or s size"
+BEFORE_DATE_E = 1036, // "before date in the future"
+AFTER_DATE_E = 1037, // "after date in the past"
+SIG_CONFIRM_E = 1038, // "bad signature confirmation"
+
+};
+
+
+struct Error {
+ ErrorNumber what_; // description number, 0 for no error
+
+ explicit Error(ErrorNumber w = NO_ERROR) : what_(w) {}
+
+ ErrorNumber What() const { return what_; }
+ void SetError(ErrorNumber w) { what_ = w; }
+};
+
+
+
+} // namespace TaoCrypt
+
+#endif // TAO_CRYPT_ERROR_HPP
diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp
new file mode 100644
index 00000000000..b27ab3aebf3
--- /dev/null
+++ b/extra/yassl/taocrypt/include/file.hpp
@@ -0,0 +1,124 @@
+/* file.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* file.hpp provies File Sources and Sinks
+*/
+
+
+#ifndef TAO_CRYPT_FILE_HPP
+#define TAO_CRYPT_FILE_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "error.hpp"
+#include <cstdio>
+
+namespace TaoCrypt {
+
+
+class Source {
+ ByteBlock buffer_;
+ word32 current_;
+ Error error_;
+public:
+ explicit Source(word32 sz = 0) : buffer_(sz), current_(0) {}
+ Source(const byte* b, word32 sz) : buffer_(b, sz), current_(0) {}
+
+ word32 size() const { return buffer_.size(); }
+ void grow(word32 sz) { buffer_.CleanGrow(sz); }
+
+ const byte* get_buffer() const { return buffer_.get_buffer(); }
+ const byte* get_current() const { return &buffer_[current_]; }
+ word32 get_index() const { return current_; }
+ void set_index(word32 i) { current_ = i; }
+
+ byte operator[] (word32 i) { current_ = i; return next(); }
+ byte next() { return buffer_[current_++]; }
+ byte prev() { return buffer_[--current_]; }
+
+ void add(const byte* data, word32 len)
+ {
+ memcpy(buffer_.get_buffer() + current_, data, len);
+ current_ += len;
+ }
+
+ void advance(word32 i) { current_ += i; }
+ void reset(ByteBlock&);
+
+ Error GetError() { return error_; }
+ void SetError(ErrorNumber w) { error_.SetError(w); }
+
+ friend class FileSource; // for get()
+private:
+ Source(const Source& that) : buffer_(that.buffer_), current_(that.current_) {}
+ Source& operator=(const Source& that)
+ {
+ Source tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(Source& other)
+ {
+ buffer_.Swap(other.buffer_);
+ mySTL::swap(current_, other.current_);
+ }
+
+};
+
+
+// File Source
+class FileSource {
+ FILE* file_;
+public:
+ FileSource(const char* fname, Source& source);
+ ~FileSource();
+
+ word32 size(bool use_current = false);
+private:
+ word32 get(Source&);
+ word32 size_left();
+
+ FileSource(const FileSource&); // hide
+ FileSource& operator=(const FileSource&); // hide
+};
+
+
+// File Sink
+class FileSink {
+ FILE* file_;
+public:
+ FileSink(const char* fname, Source& source);
+ ~FileSink();
+
+ word32 size(bool use_current = false);
+private:
+ void put(Source&);
+
+ FileSink(const FileSink&); // hide
+ FileSink& operator=(const FileSink&); // hide
+};
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_FILE_HPP
diff --git a/extra/yassl/taocrypt/include/hash.hpp b/extra/yassl/taocrypt/include/hash.hpp
new file mode 100644
index 00000000000..1703de23713
--- /dev/null
+++ b/extra/yassl/taocrypt/include/hash.hpp
@@ -0,0 +1,73 @@
+/* hash.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* hash.hpp provides a base for digest types
+*/
+
+
+#ifndef TAO_CRYPT_HASH_HPP
+#define TAO_CRYPT_HASH_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+// HASH
+class HASH {
+public:
+ virtual ~HASH() {}
+
+ virtual void Update(const byte*, word32) = 0;
+ virtual void Final(byte*) = 0;
+
+ virtual void Init() = 0;
+
+ virtual word32 getBlockSize() const = 0;
+ virtual word32 getDigestSize() const = 0;
+};
+
+
+// HASH with Transform
+class HASHwithTransform : public HASH {
+public:
+ HASHwithTransform(word32 digSz, word32 buffSz)
+ : digest_(new (tc) word32[digSz]), buffer_(new (tc) byte[buffSz]) {}
+ virtual ~HASHwithTransform() { delete[] buffer_; delete[] digest_; }
+
+ virtual ByteOrder getByteOrder() const = 0;
+ virtual word32 getPadSize() const = 0;
+
+ virtual void Update(const byte*, word32);
+ virtual void Final(byte*);
+protected:
+ word32 buffLen_;
+ word32 length_; // in Bits
+ word32* digest_;
+ byte* buffer_;
+
+ virtual void Transform() = 0;
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_HASH_HPP
diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp
new file mode 100644
index 00000000000..dcfef225d89
--- /dev/null
+++ b/extra/yassl/taocrypt/include/hmac.hpp
@@ -0,0 +1,128 @@
+/* hmac.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* hamc.hpp implements HMAC, see RFC 2104
+*/
+
+
+#ifndef TAO_CRYPT_HMAC_HPP
+#define TAO_CRYPT_HMAC_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// HMAC class template
+template <class T>
+class HMAC {
+public:
+ enum { IPAD = 0x36, OPAD = 0x5C };
+
+ HMAC() { Init(); }
+ void Update(const byte*, word32);
+ void Final(byte*);
+ void Init();
+
+ void SetKey(const byte*, word32);
+private:
+ byte ipad_[T::BLOCK_SIZE];
+ byte opad_[T::BLOCK_SIZE];
+ byte innerHash_[T::DIGEST_SIZE];
+ bool innerHashKeyed_;
+ T mac_;
+
+ void KeyInnerHash();
+
+ HMAC(const HMAC&);
+ HMAC& operator= (const HMAC&);
+};
+
+
+// Setup
+template <class T>
+void HMAC<T>::Init()
+{
+ mac_.Init();
+ innerHashKeyed_ = false;
+}
+
+
+// Key generation
+template <class T>
+void HMAC<T>::SetKey(const byte* key, word32 length)
+{
+ Init();
+
+ if (length <= T::BLOCK_SIZE)
+ memcpy(ipad_, key, length);
+ else {
+ mac_.Update(key, length);
+ mac_.Final(ipad_);
+ length = T::DIGEST_SIZE;
+ }
+ memset(ipad_ + length, 0, T::BLOCK_SIZE - length);
+
+ for (word32 i = 0; i < T::BLOCK_SIZE; i++) {
+ opad_[i] = ipad_[i] ^ OPAD;
+ ipad_[i] ^= IPAD;
+ }
+}
+
+
+// Inner Key Hash
+template <class T>
+void HMAC<T>::KeyInnerHash()
+{
+ mac_.Update(ipad_, T::BLOCK_SIZE);
+ innerHashKeyed_ = true;
+}
+
+
+// Update
+template <class T>
+void HMAC<T>::Update(const byte* msg, word32 length)
+{
+ if (!innerHashKeyed_)
+ KeyInnerHash();
+ mac_.Update(msg, length);
+}
+
+
+// Final
+template <class T>
+void HMAC<T>::Final(byte* hash)
+{
+ if (!innerHashKeyed_)
+ KeyInnerHash();
+ mac_.Final(innerHash_);
+
+ mac_.Update(opad_, T::BLOCK_SIZE);
+ mac_.Update(innerHash_, T::DIGEST_SIZE);
+ mac_.Final(hash);
+
+ innerHashKeyed_ = false;
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_HMAC_HPP
diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp
new file mode 100644
index 00000000000..94383f8061d
--- /dev/null
+++ b/extra/yassl/taocrypt/include/integer.hpp
@@ -0,0 +1,324 @@
+/* integer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's integer.h from CryptoPP */
+
+
+#ifndef TAO_CRYPT_INTEGER_HPP
+#define TAO_CRYPT_INTEGER_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "random.hpp"
+#include "file.hpp"
+#include <cstring>
+#include "algorithm.hpp" // mySTL::swap
+
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+#ifdef _M_IX86
+ #if (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)) || \
+ (defined(__ICL) && (__ICL >= 500))
+ #define SSE2_INTRINSICS_AVAILABLE
+ #define TAOCRYPT_MM_MALLOC_AVAILABLE
+ #elif defined(_MSC_VER)
+ // _mm_free seems to be the only way to tell if the Processor Pack is
+ //installed or not
+ #include <malloc.h>
+ #if defined(_mm_free)
+ #define SSE2_INTRINSICS_AVAILABLE
+ #define TAOCRYPT_MM_MALLOC_AVAILABLE
+ #endif
+ #endif
+#endif
+
+// SSE2 intrinsics work in GCC 3.3 or later
+#if defined(__SSE2__) && (__GNUC_MAJOR__ > 3 || __GNUC_MINOR__ > 2)
+ #define SSE2_INTRINSICS_AVAILABLE
+#endif
+
+#endif // X86ASM
+
+
+
+
+namespace TaoCrypt {
+
+#if defined(SSE2_INTRINSICS_AVAILABLE)
+
+ // Allocator handling proper alignment
+ template <class T>
+ class AlignedAllocator : public AllocatorBase<T>
+ {
+ public:
+ typedef typename AllocatorBase<T>::pointer pointer;
+ typedef typename AllocatorBase<T>::size_type size_type;
+
+ pointer allocate(size_type n, const void* = 0);
+ void deallocate(void* p, size_type n);
+ pointer reallocate(T* p, size_type oldSize, size_type newSize,
+ bool preserve)
+ {
+ return StdReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ #if !(defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16) || \
+ defined(TAOCRYPT_MEMALIGN_AVAILABLE) || \
+ defined(TAOCRYPT_MM_MALLOC_AVAILABLE))
+ #define TAOCRYPT_NO_ALIGNED_ALLOC
+ AlignedAllocator() : m_pBlock(0) {}
+ protected:
+ void *m_pBlock;
+ #endif
+ };
+
+ template class TAOCRYPT_DLL AlignedAllocator<word>;
+ typedef Block<word, AlignedAllocator<word> > AlignedWordBlock;
+#else
+ typedef WordBlock AlignedWordBlock;
+#endif
+
+
+// general MIN
+template<typename T> inline
+const T& min(const T& a, const T& b)
+{
+ return a < b ? a : b;
+}
+
+
+// general MAX
+template<typename T> inline
+const T& max(const T& a, const T& b)
+{
+ return a > b ? a : b;
+}
+
+
+// Large Integer class
+class Integer {
+public:
+ enum Sign {POSITIVE = 0, NEGATIVE = 1 };
+ enum Signedness { UNSIGNED, SIGNED };
+ enum RandomNumberType { ANY, PRIME };
+
+ class DivideByZero {};
+
+ Integer();
+ Integer(const Integer& t);
+ Integer(signed long value);
+ Integer(Sign s, word highWord, word lowWord);
+
+ explicit Integer(const char* str);
+ explicit Integer(const wchar_t* str);
+
+ // BER Decode Source
+ explicit Integer(Source&);
+
+ Integer(const byte* encodedInteger, unsigned int byteCount,
+ Signedness s = UNSIGNED);
+
+ ~Integer() {}
+
+ static const Integer &Zero();
+ static const Integer &One();
+ static const Integer &Two();
+
+ Integer& Ref() { return *this; }
+
+ Integer(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max);
+
+ static Integer Power2(unsigned int e);
+
+ unsigned int MinEncodedSize(Signedness = UNSIGNED) const;
+ unsigned int Encode(byte* output, unsigned int outputLen,
+ Signedness = UNSIGNED) const;
+
+ void Decode(const byte* input, unsigned int inputLen,
+ Signedness = UNSIGNED);
+ void Decode(Source&);
+
+ bool IsConvertableToLong() const;
+ signed long ConvertToLong() const;
+
+ unsigned int BitCount() const;
+ unsigned int ByteCount() const;
+ unsigned int WordCount() const;
+
+ bool GetBit(unsigned int i) const;
+ byte GetByte(unsigned int i) const;
+ unsigned long GetBits(unsigned int i, unsigned int n) const;
+
+ bool IsZero() const { return !*this; }
+ bool NotZero() const { return !IsZero(); }
+ bool IsNegative() const { return sign_ == NEGATIVE; }
+ bool NotNegative() const { return !IsNegative(); }
+ bool IsPositive() const { return NotNegative() && NotZero(); }
+ bool NotPositive() const { return !IsPositive(); }
+ bool IsEven() const { return GetBit(0) == 0; }
+ bool IsOdd() const { return GetBit(0) == 1; }
+
+ Integer& operator=(const Integer& t);
+ Integer& operator+=(const Integer& t);
+ Integer& operator-=(const Integer& t);
+ Integer& operator*=(const Integer& t) { return *this = Times(t); }
+ Integer& operator/=(const Integer& t)
+ { return *this = DividedBy(t);}
+ Integer& operator%=(const Integer& t) { return *this = Modulo(t); }
+ Integer& operator/=(word t) { return *this = DividedBy(t); }
+ Integer& operator%=(word t) { return *this = Modulo(t); }
+ Integer& operator<<=(unsigned int);
+ Integer& operator>>=(unsigned int);
+
+
+ void Randomize(RandomNumberGenerator &rng, unsigned int bitcount);
+ void Randomize(RandomNumberGenerator &rng, const Integer &min,
+ const Integer &max);
+
+ void SetBit(unsigned int n, bool value = 1);
+ void SetByte(unsigned int n, byte value);
+
+ void Negate();
+ void SetPositive() { sign_ = POSITIVE; }
+ void SetNegative() { if (!!(*this)) sign_ = NEGATIVE; }
+ void Swap(Integer& a);
+
+ bool operator!() const;
+ Integer operator+() const {return *this;}
+ Integer operator-() const;
+ Integer& operator++();
+ Integer& operator--();
+ Integer operator++(int)
+ { Integer temp = *this; ++*this; return temp; }
+ Integer operator--(int)
+ { Integer temp = *this; --*this; return temp; }
+
+ int Compare(const Integer& a) const;
+
+ Integer Plus(const Integer &b) const;
+ Integer Minus(const Integer &b) const;
+ Integer Times(const Integer &b) const;
+ Integer DividedBy(const Integer &b) const;
+ Integer Modulo(const Integer &b) const;
+ Integer DividedBy(word b) const;
+ word Modulo(word b) const;
+
+ Integer operator>>(unsigned int n) const { return Integer(*this)>>=n; }
+ Integer operator<<(unsigned int n) const { return Integer(*this)<<=n; }
+
+ Integer AbsoluteValue() const;
+ Integer Doubled() const { return Plus(*this); }
+ Integer Squared() const { return Times(*this); }
+ Integer SquareRoot() const;
+
+ bool IsSquare() const;
+ bool IsUnit() const;
+
+ Integer MultiplicativeInverse() const;
+
+ friend Integer a_times_b_mod_c(const Integer& x, const Integer& y,
+ const Integer& m);
+ friend Integer a_exp_b_mod_c(const Integer& x, const Integer& e,
+ const Integer& m);
+
+ static void Divide(Integer& r, Integer& q, const Integer& a,
+ const Integer& d);
+ static void Divide(word& r, Integer& q, const Integer& a, word d);
+ static void DivideByPowerOf2(Integer& r, Integer& q, const Integer& a,
+ unsigned int n);
+ static Integer Gcd(const Integer& a, const Integer& n);
+
+ Integer InverseMod(const Integer& n) const;
+ word InverseMod(word n) const;
+
+private:
+ friend class ModularArithmetic;
+ friend class MontgomeryRepresentation;
+ friend class HalfMontgomeryRepresentation;
+
+ Integer(word value, unsigned int length);
+
+ static const Integer zero;
+ static const Integer one;
+ static const Integer two;
+
+ int PositiveCompare(const Integer& t) const;
+ friend void PositiveAdd(Integer& sum, const Integer& a, const Integer& b);
+ friend void PositiveSubtract(Integer& diff, const Integer& a,
+ const Integer& b);
+ friend void PositiveMultiply(Integer& product, const Integer& a,
+ const Integer& b);
+ friend void PositiveDivide(Integer& remainder, Integer& quotient, const
+ Integer& dividend, const Integer& divisor);
+ AlignedWordBlock reg_;
+ Sign sign_;
+};
+
+inline bool operator==(const Integer& a, const Integer& b)
+ {return a.Compare(b)==0;}
+inline bool operator!=(const Integer& a, const Integer& b)
+ {return a.Compare(b)!=0;}
+inline bool operator> (const Integer& a, const Integer& b)
+ {return a.Compare(b)> 0;}
+inline bool operator>=(const Integer& a, const Integer& b)
+ {return a.Compare(b)>=0;}
+inline bool operator< (const Integer& a, const Integer& b)
+ {return a.Compare(b)< 0;}
+inline bool operator<=(const Integer& a, const Integer& b)
+ {return a.Compare(b)<=0;}
+
+inline Integer operator+(const Integer &a, const Integer &b)
+ {return a.Plus(b);}
+inline Integer operator-(const Integer &a, const Integer &b)
+ {return a.Minus(b);}
+inline Integer operator*(const Integer &a, const Integer &b)
+ {return a.Times(b);}
+inline Integer operator/(const Integer &a, const Integer &b)
+ {return a.DividedBy(b);}
+inline Integer operator%(const Integer &a, const Integer &b)
+ {return a.Modulo(b);}
+inline Integer operator/(const Integer &a, word b) {return a.DividedBy(b);}
+inline word operator%(const Integer &a, word b) {return a.Modulo(b);}
+
+inline void swap(Integer &a, Integer &b)
+{
+ a.Swap(b);
+}
+
+
+Integer CRT(const Integer& xp, const Integer& p, const Integer& xq,
+ const Integer& q, const Integer& u);
+inline Integer ModularExponentiation(const Integer& a, const Integer& e,
+ const Integer& m)
+{
+ return a_exp_b_mod_c(a, e, m);
+}
+
+Integer ModularRoot(const Integer& a, const Integer& dp, const Integer& dq,
+ const Integer& p, const Integer& q, const Integer& u);
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_INTEGER_HPP
diff --git a/extra/yassl/taocrypt/include/md2.hpp b/extra/yassl/taocrypt/include/md2.hpp
new file mode 100644
index 00000000000..1e1c17e9cbe
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md2.hpp
@@ -0,0 +1,67 @@
+/* md5.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* md2.hpp provides MD2 digest support, see RFC 1319
+*/
+
+#ifndef TAO_CRYPT_MD2_HPP
+#define TAO_CRYPT_MD2_HPP
+
+
+#include "hash.hpp"
+#include "block.hpp"
+
+
+namespace TaoCrypt {
+
+
+// MD2 digest
+class MD2 : public HASH {
+public:
+ enum { BLOCK_SIZE = 16, DIGEST_SIZE = 16, PAD_SIZE = 16, X_SIZE = 48 };
+ MD2();
+
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+
+ void Update(const byte*, word32);
+ void Final(byte*);
+
+ void Init();
+ void Swap(MD2&);
+private:
+ ByteBlock X_, C_, buffer_;
+ word32 count_; // bytes % PAD_SIZE
+
+ MD2(const MD2&);
+ MD2& operator=(const MD2&);
+};
+
+inline void swap(MD2& a, MD2& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD2_HPP
+
diff --git a/extra/yassl/taocrypt/include/md5.hpp b/extra/yassl/taocrypt/include/md5.hpp
new file mode 100644
index 00000000000..0198daa466e
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md5.hpp
@@ -0,0 +1,63 @@
+/* md5.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* md5.hpp provides MD5 digest support, see RFC 1321
+*/
+
+#ifndef TAO_CRYPT_MD5_HPP
+#define TAO_CRYPT_MD5_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// MD5 digest
+class MD5 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ MD5() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ MD5(const MD5&);
+ MD5& operator= (const MD5&);
+
+ void Init();
+ void Swap(MD5&);
+private:
+ void Transform();
+};
+
+inline void swap(MD5& a, MD5& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD5_HPP
+
diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp
new file mode 100644
index 00000000000..01a3e8ee731
--- /dev/null
+++ b/extra/yassl/taocrypt/include/misc.hpp
@@ -0,0 +1,776 @@
+/* misc.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's misc.h from CryptoPP */
+
+#ifndef TAO_CRYPT_MISC_HPP
+#define TAO_CRYPT_MISC_HPP
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+namespace TaoCrypt {
+
+// library allocation
+struct new_t {}; // TaoCrypt New type
+extern new_t tc; // pass in parameter
+
+} // namespace TaoCrypt
+
+void* operator new (size_t, TaoCrypt::new_t);
+void* operator new[](size_t, TaoCrypt::new_t);
+
+
+namespace TaoCrypt {
+
+
+// define this if running on a big-endian CPU
+#if !defined(LITTLE_ENDIAN_ORDER) && (defined(__BIG_ENDIAN__) || \
+ defined(__sparc) || defined(__sparc__) || defined(__hppa__) || \
+ defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__)))
+ #define BIG_ENDIAN_ORDER
+#endif
+
+#ifndef BIG_ENDIAN_ORDER
+ #define LITTLE_ENDIAN_ORDER
+#endif
+
+
+typedef unsigned char byte;
+typedef unsigned short word16;
+typedef unsigned int word32;
+
+#if defined(__GNUC__) || defined(__MWERKS__)
+ #define WORD64_AVAILABLE
+ typedef unsigned long long word64;
+ #define W64LIT(x) x##LL
+#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define WORD64_AVAILABLE
+ typedef unsigned __int64 word64;
+ #define W64LIT(x) x##ui64
+#elif defined(__DECCXX)
+ #define WORD64_AVAILABLE
+ typedef unsigned long word64;
+#endif
+
+// define largest word type
+#ifdef WORD64_AVAILABLE
+ typedef word64 lword;
+#else
+ typedef word32 lword;
+#endif
+
+#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \
+ defined(__x86_64__) || defined(__mips64)
+// These platforms have 64-bit CPU registers. Unfortunately most C++ compilers
+// don't allow any way to access the 64-bit by 64-bit multiply instruction
+// without using assembly, so in order to use word64 as word, the assembly
+// instruction must be defined in Dword::Multiply().
+ typedef word32 hword;
+ typedef word64 word;
+#else
+ #define TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ #ifdef WORD64_AVAILABLE
+ #define TAOCRYPT_SLOW_WORD64
+ // define this if your CPU is not64-bit to use alternative code
+ // that avoids word64
+ typedef word16 hword;
+ typedef word32 word;
+ typedef word64 dword;
+ #else
+ typedef word8 hword;
+ typedef word16 word;
+ typedef word32 dword;
+ #endif
+#endif
+
+const word32 WORD_SIZE = sizeof(word);
+const word32 WORD_BITS = WORD_SIZE * 8;
+
+
+#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define INTEL_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+ #define PPC_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__GNUC__) && defined(__i386__)
+ // GCC does peephole optimizations which should result in using rotate
+ // instructions
+ #define FAST_ROTATE
+#endif
+
+
+// no gas on these systems ?, disable for now
+#if defined(__sun__) || defined (__QNX__)
+ #define TAOCRYPT_DISABLE_X86ASM
+#endif
+
+
+
+// CodeWarrior defines _MSC_VER
+#if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \
+ !defined(__MWERKS__) && defined(_M_IX86)) || \
+ (defined(__GNUC__) && defined(__i386__)))
+ #define TAOCRYPT_X86ASM_AVAILABLE
+#endif
+
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# define TAOCRYPT_MALLOC_ALIGNMENT_IS_16
+#endif
+
+#if defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+# define TAOCRYPT_MEMALIGN_AVAILABLE
+#endif
+
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ #define TAOCRYPT_WIN32_AVAILABLE
+#endif
+
+#if defined(__unix__) || defined(__MACH__)
+ #define TAOCRYPT_UNIX_AVAILABLE
+#endif
+
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ #define CPP_TYPENAME
+#else
+ #define CPP_TYPENAME typename
+#endif
+
+
+#ifdef _MSC_VER
+ #define TAOCRYPT_NO_VTABLE __declspec(novtable)
+#else
+ #define TAOCRYPT_NO_VTABLE
+#endif
+
+
+// ***************** DLL related ********************
+
+#ifdef TAOCRYPT_WIN32_AVAILABLE
+
+#ifdef TAOCRYPT_EXPORTS
+ #define TAOCRYPT_IS_DLL
+ #define TAOCRYPT_DLL __declspec(dllexport)
+#elif defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_IS_DLL
+ #define TAOCRYPT_DLL __declspec(dllimport)
+#else
+ #define TAOCRYPT_DLL
+#endif // EXPORTS
+
+#define TAOCRYPT_API __stdcall
+#define TAOCRYPT_CDECL __cdecl
+
+#else // TAOCRYPT_WIN32_AVAILABLE
+
+#define TAOCRYPT_DLL
+#define TAOCRYPT_API
+#define TAOCRYPT_CDECL
+
+#endif // TAOCRYPT_WIN32_AVAILABLE
+
+
+// ****************** tempalte stuff *******************
+
+
+#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
+ !defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS template class TAOCRYPT_DLL
+#elif defined(__MWERKS__)
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS extern class TAOCRYPT_DLL
+#else
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS extern template class TAOCRYPT_DLL
+#endif
+
+
+#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
+ !defined(TAOCRYPT_EXPORTS)
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS template class
+#elif defined(__MWERKS__)
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern class
+#else
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+
+// ************** compile-time assertion ***************
+
+template <bool b>
+struct CompileAssert
+{
+ static char dummy[2*b-1];
+};
+
+#define TAOCRYPT_COMPILE_ASSERT(assertion) \
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
+
+#if defined(TAOCRYPT_EXPORTS) || defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance)
+#else
+ #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance) \
+ (void)sizeof(CompileAssert<(assertion)>)
+#endif
+
+#define TAOCRYPT_ASSERT_JOIN(X, Y) TAOCRYPT_DO_ASSERT_JOIN(X, Y)
+
+#define TAOCRYPT_DO_ASSERT_JOIN(X, Y) X##Y
+
+
+/*************** helpers *****************************/
+
+inline unsigned int BitsToBytes(unsigned int bitCount)
+{
+ return ((bitCount+7)/(8));
+}
+
+inline unsigned int BytesToWords(unsigned int byteCount)
+{
+ return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
+}
+
+inline unsigned int BitsToWords(unsigned int bitCount)
+{
+ return ((bitCount+WORD_BITS-1)/(WORD_BITS));
+}
+
+inline void CopyWords(word* r, const word* a, word32 n)
+{
+ for (word32 i = 0; i < n; i++)
+ r[i] = a[i];
+}
+
+inline unsigned int CountWords(const word* X, unsigned int N)
+{
+ while (N && X[N-1]==0)
+ N--;
+ return N;
+}
+
+inline void SetWords(word* r, word a, unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ r[i] = a;
+}
+
+enum ByteOrder { LittleEndianOrder = 0, BigEndianOrder = 1 };
+enum CipherDir {ENCRYPTION, DECRYPTION};
+
+inline CipherDir ReverseDir(CipherDir dir)
+{
+ return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
+}
+
+template <typename ENUM_TYPE, int VALUE>
+struct EnumToType
+{
+ static ENUM_TYPE ToEnum() { return (ENUM_TYPE)VALUE; }
+};
+
+typedef EnumToType<ByteOrder, LittleEndianOrder> LittleEndian;
+typedef EnumToType<ByteOrder, BigEndianOrder> BigEndian;
+
+
+#ifndef BIG_ENDIAN_ORDER
+ typedef LittleEndian HostByteOrder;
+#else
+ typedef BigEndian HostByteOrder;
+#endif
+
+inline ByteOrder GetHostByteOrder()
+{
+ return HostByteOrder::ToEnum();
+}
+
+inline bool HostByteOrderIs(ByteOrder order)
+{
+ return order == GetHostByteOrder();
+}
+
+
+void xorbuf(byte*, const byte*, unsigned int);
+
+
+template <class T>
+inline bool IsPowerOf2(T n)
+{
+ return n > 0 && (n & (n-1)) == 0;
+}
+
+template <class T1, class T2>
+inline T2 ModPowerOf2(T1 a, T2 b)
+{
+ assert(IsPowerOf2(b));
+ return T2(a) & (b-1);
+}
+
+template <class T>
+inline T RoundDownToMultipleOf(T n, T m)
+{
+ return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
+}
+
+template <class T>
+inline T RoundUpToMultipleOf(T n, T m)
+{
+ return RoundDownToMultipleOf(n+m-1, m);
+}
+
+template <class T>
+inline unsigned int GetAlignment(T* dummy = 0) // VC60 workaround
+{
+#if (_MSC_VER >= 1300)
+ return __alignof(T);
+#elif defined(__GNUC__)
+ return __alignof__(T);
+#else
+ return sizeof(T);
+#endif
+}
+
+inline bool IsAlignedOn(const void* p, unsigned int alignment)
+{
+ return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0
+ : (size_t)p % alignment == 0;
+}
+
+template <class T>
+inline bool IsAligned(const void* p, T* dummy = 0) // VC60 workaround
+{
+ return IsAlignedOn(p, GetAlignment<T>());
+}
+
+
+template <class T> inline T rotlFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return (x<<y) | (x>>(sizeof(T)*8-y));
+}
+
+template <class T> inline T rotrFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return (x>>y) | (x<<(sizeof(T)*8-y));
+}
+
+#ifdef INTEL_INTRINSICS
+
+#pragma intrinsic(_lrotl, _lrotr)
+
+template<> inline word32 rotlFixed(word32 x, word32 y)
+{
+ assert(y < 32);
+ return y ? _lrotl(x, y) : x;
+}
+
+template<> inline word32 rotrFixed(word32 x, word32 y)
+{
+ assert(y < 32);
+ return y ? _lrotr(x, y) : x;
+}
+
+#endif // INTEL_INTRINSICS
+
+#ifdef min
+#undef min
+#endif
+
+inline word32 min(word32 a, word32 b)
+{
+ return a < b ? a : b;
+}
+
+
+inline word32 ByteReverse(word32 value)
+{
+#ifdef PPC_INTRINSICS
+ // PPC: load reverse indexed instruction
+ return (word32)__lwbrx(&value,0);
+#elif defined(FAST_ROTATE)
+ // 5 instructions with rotate instruction, 9 without
+ return (rotrFixed(value, 8U) & 0xff00ff00) |
+ (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+ // 6 instructions with rotate instruction, 8 without
+ value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+ return rotlFixed(value, 16U);
+#endif
+}
+
+
+template <typename T>
+inline void ByteReverse(T* out, const T* in, word32 byteCount)
+{
+ assert(byteCount % sizeof(T) == 0);
+ word32 count = byteCount/sizeof(T);
+ for (word32 i=0; i<count; i++)
+ out[i] = ByteReverse(in[i]);
+}
+
+inline void ByteReverse(byte* out, const byte* in, word32 byteCount)
+{
+ word32* o = reinterpret_cast<word32*>(out);
+ const word32* i = reinterpret_cast<const word32*>(in);
+ ByteReverse(o, i, byteCount);
+}
+
+
+template <class T>
+inline T ByteReverseIf(T value, ByteOrder order)
+{
+ return HostByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+
+template <typename T>
+inline void ByteReverseIf(T* out, const T* in, word32 bc, ByteOrder order)
+{
+ if (!HostByteOrderIs(order))
+ ByteReverse(out, in, bc);
+ else if (out != in)
+ memcpy(out, in, bc);
+}
+
+
+template <class T>
+inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in,
+ word32 inlen)
+{
+ const unsigned int U = sizeof(T);
+ assert(inlen <= outlen*U);
+ memcpy(out, in, inlen);
+ memset((byte *)out+inlen, 0, outlen*U-inlen);
+ ByteReverseIf(out, out, RoundUpToMultipleOf(inlen, U), order);
+}
+
+
+#ifdef _MSC_VER
+ // disable conversion warning
+ #pragma warning(disable:4244)
+#endif
+
+
+inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block,
+ byte*)
+{
+ return block[0];
+}
+
+inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
+ word16*)
+{
+ return (order == BigEndianOrder)
+ ? block[1] | (block[0] << 8)
+ : block[0] | (block[1] << 8);
+}
+
+inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
+ word32*)
+{
+ return (order == BigEndianOrder)
+ ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16)
+ | (word32(block[0]) << 24)
+ : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16)
+ | (word32(block[3]) << 24);
+}
+
+template <class T>
+inline T UnalignedGetWord(ByteOrder order, const byte *block, T* dummy = 0)
+{
+ return UnalignedGetWordNonTemplate(order, block, dummy);
+}
+
+inline void UnalignedPutWord(ByteOrder order, byte *block, byte value,
+ const byte *xorBlock = 0)
+{
+ block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
+}
+
+#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
+
+inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value,
+ const byte *xorBlock = 0)
+{
+ if (order == BigEndianOrder)
+ {
+ block[0] = GETBYTE(value, 1);
+ block[1] = GETBYTE(value, 0);
+ }
+ else
+ {
+ block[0] = GETBYTE(value, 0);
+ block[1] = GETBYTE(value, 1);
+ }
+
+ if (xorBlock)
+ {
+ block[0] ^= xorBlock[0];
+ block[1] ^= xorBlock[1];
+ }
+}
+
+inline void UnalignedPutWord(ByteOrder order, byte* block, word32 value,
+ const byte* xorBlock = 0)
+{
+ if (order == BigEndianOrder)
+ {
+ block[0] = GETBYTE(value, 3);
+ block[1] = GETBYTE(value, 2);
+ block[2] = GETBYTE(value, 1);
+ block[3] = GETBYTE(value, 0);
+ }
+ else
+ {
+ block[0] = GETBYTE(value, 0);
+ block[1] = GETBYTE(value, 1);
+ block[2] = GETBYTE(value, 2);
+ block[3] = GETBYTE(value, 3);
+ }
+
+ if (xorBlock)
+ {
+ block[0] ^= xorBlock[0];
+ block[1] ^= xorBlock[1];
+ block[2] ^= xorBlock[2];
+ block[3] ^= xorBlock[3];
+ }
+}
+
+
+template <class T>
+inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
+{
+ if (assumeAligned)
+ {
+ assert(IsAligned<T>(block));
+ return ByteReverseIf(*reinterpret_cast<const T *>(block), order);
+ }
+ else
+ return UnalignedGetWord<T>(order, block);
+}
+
+template <class T>
+inline void GetWord(bool assumeAligned, ByteOrder order, T &result,
+ const byte *block)
+{
+ result = GetWord<T>(assumeAligned, order, block);
+}
+
+template <class T>
+inline void PutWord(bool assumeAligned, ByteOrder order, byte* block, T value,
+ const byte *xorBlock = 0)
+{
+ if (assumeAligned)
+ {
+ assert(IsAligned<T>(block));
+ if (xorBlock)
+ *reinterpret_cast<T *>(block) = ByteReverseIf(value, order)
+ ^ *reinterpret_cast<const T *>(xorBlock);
+ else
+ *reinterpret_cast<T *>(block) = ByteReverseIf(value, order);
+ }
+ else
+ UnalignedPutWord(order, block, value, xorBlock);
+}
+
+template <class T, class B, bool A=true>
+class GetBlock
+{
+public:
+ GetBlock(const void *block)
+ : m_block((const byte *)block) {}
+
+ template <class U>
+ inline GetBlock<T, B, A> & operator()(U &x)
+ {
+ TAOCRYPT_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
+ x = GetWord<T>(A, B::ToEnum(), m_block);
+ m_block += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_block;
+};
+
+template <class T, class B, bool A = true>
+class PutBlock
+{
+public:
+ PutBlock(const void *xorBlock, void *block)
+ : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
+
+ template <class U>
+ inline PutBlock<T, B, A> & operator()(U x)
+ {
+ PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
+ m_block += sizeof(T);
+ if (m_xorBlock)
+ m_xorBlock += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_xorBlock;
+ byte *m_block;
+};
+
+template <class T, class B, bool A=true>
+struct BlockGetAndPut
+{
+ // function needed because of C++ grammatical ambiguity between
+ // expression-statements and declarations
+ static inline GetBlock<T, B, A> Get(const void *block)
+ {return GetBlock<T, B, A>(block);}
+ typedef PutBlock<T, B, A> Put;
+};
+
+
+
+template <bool overflow> struct SafeShifter;
+
+template<> struct SafeShifter<true>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+};
+
+template<> struct SafeShifter<false>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return value >> bits;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return value << bits;
+ }
+};
+
+template <unsigned int bits, class T>
+inline T SafeRightShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
+}
+
+template <unsigned int bits, class T>
+inline T SafeLeftShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
+}
+
+
+inline
+word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (unsigned int i=0; i<n; i++)
+ {
+ u = r[i];
+ r[i] = (u << shiftBits) | carry;
+ carry = u >> (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+
+inline
+word ShiftWordsRightByBits(word* r, unsigned int n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (int i=n-1; i>=0; i--)
+ {
+ u = r[i];
+ r[i] = (u >> shiftBits) | carry;
+ carry = u << (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+
+inline
+void ShiftWordsLeftByWords(word* r, unsigned int n, unsigned int shiftWords)
+{
+ shiftWords = min(shiftWords, n);
+ if (shiftWords)
+ {
+ for (unsigned int i=n-1; i>=shiftWords; i--)
+ r[i] = r[i-shiftWords];
+ SetWords(r, 0, shiftWords);
+ }
+}
+
+
+inline
+void ShiftWordsRightByWords(word* r, unsigned int n, unsigned int shiftWords)
+{
+ shiftWords = min(shiftWords, n);
+ if (shiftWords)
+ {
+ for (unsigned int i=0; i+shiftWords<n; i++)
+ r[i] = r[i+shiftWords];
+ SetWords(r+n-shiftWords, 0, shiftWords);
+ }
+}
+
+
+template <class T1, class T2>
+inline T1 SaturatingSubtract(T1 a, T2 b)
+{
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0); // T1 is unsigned type
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1); // T2 is unsigned type
+ return T1((a > b) ? (a - b) : 0);
+}
+
+
+// declares
+unsigned int BytePrecision(unsigned long value);
+unsigned int BitPrecision(unsigned long);
+unsigned long Crop(unsigned long value, unsigned int size);
+
+void CallNewHandler();
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MISC_HPP
diff --git a/extra/yassl/taocrypt/include/modarith.hpp b/extra/yassl/taocrypt/include/modarith.hpp
new file mode 100644
index 00000000000..88a2cc95c7c
--- /dev/null
+++ b/extra/yassl/taocrypt/include/modarith.hpp
@@ -0,0 +1,169 @@
+/* modarith.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's modarith.h from CryptoPP */
+
+
+#ifndef TAO_CRYPT_MODARITH_HPP
+#define TAO_CRYPT_MODARITH_HPP
+
+#include "misc.hpp"
+#include "integer.hpp"
+#include "algebra.hpp"
+
+namespace TaoCrypt {
+
+
+//! ModularArithmetic
+class ModularArithmetic : public AbstractRing<Integer>
+{
+public:
+
+ typedef int RandomizationParameter;
+ typedef Integer Element;
+
+ ModularArithmetic(const Integer &modulus = Integer::One())
+ : modulus(modulus), result((word)0, modulus.reg_.size()) {}
+
+ ModularArithmetic(const ModularArithmetic &ma)
+ : AbstractRing<Integer>(),
+ modulus(ma.modulus), result((word)0, modulus.reg_.size()) {}
+
+ const Integer& GetModulus() const {return modulus;}
+ void SetModulus(const Integer &newModulus)
+ {
+ modulus = newModulus;
+ result.reg_.resize(modulus.reg_.size());
+ }
+
+ virtual bool IsMontgomeryRepresentation() const {return false;}
+
+ virtual Integer ConvertIn(const Integer &a) const
+ {return a%modulus;}
+
+ virtual Integer ConvertOut(const Integer &a) const
+ {return a;}
+
+ const Integer& Half(const Integer &a) const;
+
+ bool Equal(const Integer &a, const Integer &b) const
+ {return a==b;}
+
+ const Integer& Identity() const
+ {return Integer::Zero();}
+
+ const Integer& Add(const Integer &a, const Integer &b) const;
+
+ Integer& Accumulate(Integer &a, const Integer &b) const;
+
+ const Integer& Inverse(const Integer &a) const;
+
+ const Integer& Subtract(const Integer &a, const Integer &b) const;
+
+ Integer& Reduce(Integer &a, const Integer &b) const;
+
+ const Integer& Double(const Integer &a) const
+ {return Add(a, a);}
+
+ const Integer& MultiplicativeIdentity() const
+ {return Integer::One();}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const
+ {return result1 = a*b%modulus;}
+
+ const Integer& Square(const Integer &a) const
+ {return result1 = a.Squared()%modulus;}
+
+ bool IsUnit(const Integer &a) const
+ {return Integer::Gcd(a, modulus).IsUnit();}
+
+ const Integer& MultiplicativeInverse(const Integer &a) const
+ {return result1 = a.InverseMod(modulus);}
+
+ const Integer& Divide(const Integer &a, const Integer &b) const
+ {return Multiply(a, MultiplicativeInverse(b));}
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1,
+ const Integer &y, const Integer &e2) const;
+
+ void SimultaneousExponentiate(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const;
+
+ unsigned int MaxElementBitLength() const
+ {return (modulus-1).BitCount();}
+
+ unsigned int MaxElementByteLength() const
+ {return (modulus-1).ByteCount();}
+
+
+ static const RandomizationParameter DefaultRandomizationParameter;
+
+protected:
+ Integer modulus;
+ mutable Integer result, result1;
+
+};
+
+
+
+//! do modular arithmetics in Montgomery representation for increased speed
+class MontgomeryRepresentation : public ModularArithmetic
+{
+public:
+ MontgomeryRepresentation(const Integer &modulus); // modulus must be odd
+
+ bool IsMontgomeryRepresentation() const {return true;}
+
+ Integer ConvertIn(const Integer &a) const
+ {return (a<<(WORD_BITS*modulus.reg_.size()))%modulus;}
+
+ Integer ConvertOut(const Integer &a) const;
+
+ const Integer& MultiplicativeIdentity() const
+ {return result1 = Integer::Power2(WORD_BITS*modulus.reg_.size())%modulus;}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const;
+
+ const Integer& Square(const Integer &a) const;
+
+ const Integer& MultiplicativeInverse(const Integer &a) const;
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1,
+ const Integer &y, const Integer &e2) const
+ {return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousExponentiate(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const
+ {AbstractRing<Integer>::SimultaneousExponentiate(results, base,
+ exponents, exponentsCount);}
+
+private:
+ Integer u;
+ mutable AlignedWordBlock workspace;
+};
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MODARITH_HPP
diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp
new file mode 100644
index 00000000000..2a21ad46b76
--- /dev/null
+++ b/extra/yassl/taocrypt/include/modes.hpp
@@ -0,0 +1,133 @@
+/* modes.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* modes.hpp provides ECB and CBC modes for block cipher encryption/decryption
+*/
+
+
+#ifndef TAO_CRYPT_MODES_HPP
+#define TAO_CRYPT_MODES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+enum Mode { ECB, CBC };
+
+
+// BlockCipher abstraction
+template<CipherDir DIR, class T, Mode MODE>
+class BlockCipher {
+public:
+ BlockCipher() : cipher_(DIR, MODE) {}
+
+ void Process(byte* c, const byte* p, word32 sz)
+ { cipher_.Process(c, p, sz); }
+ void SetKey(const byte* k, word32 sz)
+ { cipher_.SetKey(k, sz, DIR); }
+ void SetKey(const byte* k, word32 sz, const byte* iv)
+ { cipher_.SetKey(k, sz, DIR); cipher_.SetIV(iv); }
+private:
+ T cipher_;
+
+ BlockCipher(const BlockCipher&); // hide copy
+ BlockCipher& operator=(const BlockCipher&); // and assign
+};
+
+
+// Mode Base for block ciphers, static size
+template<int BLOCK_SIZE>
+class Mode_BASE {
+public:
+ Mode_BASE() {}
+ virtual ~Mode_BASE() {}
+
+ virtual void ProcessAndXorBlock(const byte*, const byte*, byte*) const = 0;
+
+ void ECB_Process(byte*, const byte*, word32);
+ void CBC_Encrypt(byte*, const byte*, word32);
+ void CBC_Decrypt(byte*, const byte*, word32);
+
+ void SetIV(const byte* iv) { memcpy(reg_, iv, BLOCK_SIZE); }
+private:
+ byte reg_[BLOCK_SIZE];
+ byte tmp_[BLOCK_SIZE];
+
+ Mode_BASE(const Mode_BASE&); // hide copy
+ Mode_BASE& operator=(const Mode_BASE&); // and assign
+};
+
+
+// ECB Process blocks
+template<int BLOCK_SIZE>
+void Mode_BASE<BLOCK_SIZE>::ECB_Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ while (blocks--) {
+ ProcessAndXorBlock(in, 0, out);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+
+// CBC Encrypt
+template<int BLOCK_SIZE>
+void Mode_BASE<BLOCK_SIZE>::CBC_Encrypt(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ while (blocks--) {
+ xorbuf(reg_, in, BLOCK_SIZE);
+ ProcessAndXorBlock(reg_, 0, reg_);
+ memcpy(out, reg_, BLOCK_SIZE);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+
+// CBC Decrypt
+template<int BLOCK_SIZE>
+void Mode_BASE<BLOCK_SIZE>::CBC_Decrypt(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+ byte hold[BLOCK_SIZE];
+
+ while (blocks--) {
+ memcpy(tmp_, in, BLOCK_SIZE);
+ ProcessAndXorBlock(tmp_, 0, out);
+ xorbuf(out, reg_, BLOCK_SIZE);
+ memcpy(hold, reg_, BLOCK_SIZE); // swap reg_ and tmp_
+ memcpy(reg_, tmp_, BLOCK_SIZE);
+ memcpy(tmp_, hold, BLOCK_SIZE);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MODES_HPP
diff --git a/extra/yassl/taocrypt/include/random.hpp b/extra/yassl/taocrypt/include/random.hpp
new file mode 100644
index 00000000000..5fdda8da47a
--- /dev/null
+++ b/extra/yassl/taocrypt/include/random.hpp
@@ -0,0 +1,87 @@
+/* random.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* random.hpp provides a crypto secure Random Number Generator using an OS
+ specific seed
+*/
+
+
+#ifndef TAO_CRYPT_RANDOM_HPP
+#define TAO_CRYPT_RANDOM_HPP
+
+#include "arc4.hpp"
+#include "error.hpp"
+
+namespace TaoCrypt {
+
+
+// OS specific seeder
+class OS_Seed {
+public:
+ OS_Seed();
+ ~OS_Seed();
+
+ void GenerateSeed(byte*, word32 sz);
+ Error GetError() const { return error_; }
+private:
+#if defined(WIN32)
+ #if defined(_WIN64)
+ typedef unsigned __int64 ProviderHandle;
+ // type HCRYPTPROV, avoid #include <windows.h>
+ #else
+ typedef unsigned long ProviderHandle;
+ #endif
+ ProviderHandle handle_;
+#else
+ int fd_;
+#endif
+ Error error_;
+
+ OS_Seed(const OS_Seed&); // hide copy
+ OS_Seed& operator=(const OS_Seed&); // hide assign
+};
+
+
+// secure Random Nnumber Generator
+class RandomNumberGenerator {
+public:
+ RandomNumberGenerator();
+ ~RandomNumberGenerator() {}
+
+ void GenerateBlock(byte*, word32 sz);
+ byte GenerateByte();
+
+ ErrorNumber GetError() const { return seed_.GetError().What(); }
+private:
+ OS_Seed seed_;
+ ARC4 cipher_;
+
+ RandomNumberGenerator(const RandomNumberGenerator&); // hide copy
+ RandomNumberGenerator operator=(const RandomNumberGenerator&); // && assign
+};
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RANDOM_HPP
+
diff --git a/extra/yassl/taocrypt/include/ripemd.hpp b/extra/yassl/taocrypt/include/ripemd.hpp
new file mode 100644
index 00000000000..4f8e1fd0386
--- /dev/null
+++ b/extra/yassl/taocrypt/include/ripemd.hpp
@@ -0,0 +1,63 @@
+/* ripemd.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* ripemd.hpp provides RIPEMD digest support
+*/
+
+#ifndef TAO_CRYPT_RIPEMD_HPP
+#define TAO_CRYPT_RIPEMD_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// RIPEMD160 digest
+class RIPEMD160 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ RIPEMD160() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ RIPEMD160(const RIPEMD160&);
+ RIPEMD160& operator= (const RIPEMD160&);
+
+ void Init();
+ void Swap(RIPEMD160&);
+private:
+ void Transform();
+};
+
+inline void swap(RIPEMD160& a, RIPEMD160& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RIPEMD_HPP
+
diff --git a/extra/yassl/taocrypt/include/rsa.hpp b/extra/yassl/taocrypt/include/rsa.hpp
new file mode 100644
index 00000000000..916476c90b7
--- /dev/null
+++ b/extra/yassl/taocrypt/include/rsa.hpp
@@ -0,0 +1,253 @@
+/* rsa.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* rsa.hpp provides RSA ES encrypt/decrypt, SSL (block type 1) sign and verify
+*/
+
+#ifndef TAO_CRYPT_RSA_HPP
+#define TAO_CRYPT_RSA_HPP
+
+#include "integer.hpp"
+#include "random.hpp"
+#include "stdexcept.hpp"
+
+
+namespace TaoCrypt {
+
+class Source;
+
+
+// Public Key Length helper
+class PK_Lengths {
+ const Integer& image_;
+public:
+ explicit PK_Lengths(const Integer& i) : image_(i) {}
+
+ word32 PaddedBlockBitLength() const {return image_.BitCount() - 1;}
+ word32 PaddedBlockByteLength() const
+ {return BitsToBytes(PaddedBlockBitLength());}
+
+ word32 FixedCiphertextLength() const {return image_.ByteCount();}
+ word32 FixedMaxPlaintextLength() const
+ {return SaturatingSubtract(PaddedBlockBitLength() / 8, 10U); }
+};
+
+
+// RSA Public Key
+class RSA_PublicKey {
+protected:
+ Integer n_;
+ Integer e_;
+public:
+ RSA_PublicKey() {}
+ explicit RSA_PublicKey(Source&);
+
+ void Initialize(const Integer& n, const Integer& e) {n_ = n; e_ = e;}
+ void Initialize(Source&);
+
+ Integer ApplyFunction(const Integer& x) const;
+
+ const Integer& GetModulus() const {return n_;}
+ const Integer& GetPublicExponent() const {return e_;}
+
+ void SetModulus(const Integer& n) {n_ = n;}
+ void SetPublicExponent(const Integer& e) {e_ = e;}
+
+ word32 FixedCiphertextLength()
+ {
+ return PK_Lengths(n_).FixedCiphertextLength();
+ }
+
+ RSA_PublicKey(const RSA_PublicKey& other) : n_(other.n_), e_(other.e_) {}
+ RSA_PublicKey& operator=(const RSA_PublicKey& that)
+ {
+ RSA_PublicKey tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(RSA_PublicKey& other)
+ {
+ n_.Swap(other.n_);
+ e_.Swap(other.e_);
+ }
+};
+
+
+// RSA Private Key
+class RSA_PrivateKey : public RSA_PublicKey {
+ Integer d_;
+ Integer p_;
+ Integer q_;
+ Integer dp_;
+ Integer dq_;
+ Integer u_;
+public:
+ RSA_PrivateKey() {}
+ explicit RSA_PrivateKey(Source&);
+
+ void Initialize(const Integer& n, const Integer& e, const Integer& d,
+ const Integer& p, const Integer& q, const Integer& dp,
+ const Integer& dq, const Integer& u)
+ {n_ = n; e_ = e; d_ = d; p_ = p; q_ = q; dp_ = dp; dq_ = dq; u_ = u;}
+ void Initialize(Source&);
+
+ Integer CalculateInverse(RandomNumberGenerator&, const Integer&) const;
+
+ const Integer& GetPrime1() const {return p_;}
+ const Integer& GetPrime2() const {return q_;}
+ const Integer& GetPrivateExponent() const {return d_;}
+ const Integer& GetModPrime1PrivateExponent() const {return dp_;}
+ const Integer& GetModPrime2PrivateExponent() const {return dq_;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const
+ {return u_;}
+
+ void SetPrime1(const Integer& p) {p_ = p;}
+ void SetPrime2(const Integer& q) {q_ = q;}
+ void SetPrivateExponent(const Integer& d) {d_ = d;}
+ void SetModPrime1PrivateExponent(const Integer& dp) {dp_ = dp;}
+ void SetModPrime2PrivateExponent(const Integer& dq) {dq_ = dq;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer& u) {u_ = u;}
+private:
+ RSA_PrivateKey(const RSA_PrivateKey&); // hide copy
+ RSA_PrivateKey& operator=(const RSA_PrivateKey&); // and assign
+};
+
+
+// block type 2 padding
+class RSA_BlockType2 {
+public:
+ void Pad(const byte*, word32, byte*, word32,
+ RandomNumberGenerator&) const;
+ word32 UnPad(const byte*, word32, byte*) const;
+};
+
+
+// block type 1 padding
+class RSA_BlockType1 {
+public:
+ void Pad(const byte*, word32, byte*, word32,
+ RandomNumberGenerator&) const;
+ word32 UnPad(const byte*, word32, byte*) const;
+};
+
+
+// RSA Encryptor, can use any padding
+template<class Pad = RSA_BlockType2>
+class RSA_Encryptor {
+ const RSA_PublicKey& key_;
+ Pad padding_;
+public:
+ explicit RSA_Encryptor(const RSA_PublicKey& k) : key_(k) {}
+
+ void Encrypt(const byte*, word32, byte*, RandomNumberGenerator&);
+ bool SSL_Verify(const byte* msg, word32 sz, const byte* sig);
+};
+
+
+// RSA Decryptor, can use any padding
+template<class Pad = RSA_BlockType2>
+class RSA_Decryptor {
+ const RSA_PrivateKey& key_;
+ Pad padding_;
+public:
+ explicit RSA_Decryptor(const RSA_PrivateKey& k) : key_(k) {}
+
+ word32 Decrypt(const byte*, word32, byte*, RandomNumberGenerator&);
+ void SSL_Sign(const byte*, word32, byte*, RandomNumberGenerator&);
+};
+
+
+// Public Encrypt
+template<class Pad>
+void RSA_Encryptor<Pad>::Encrypt(const byte* plain, word32 sz, byte* cipher,
+ RandomNumberGenerator& rng)
+{
+ PK_Lengths lengths(key_.GetModulus());
+ assert(sz <= lengths.FixedMaxPlaintextLength());
+
+ ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
+ padding_.Pad(plain, sz, paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), rng);
+
+ key_.ApplyFunction(Integer(paddedBlock.get_buffer(), paddedBlock.size())).
+ Encode(cipher, lengths.FixedCiphertextLength());
+}
+
+
+// Private Decrypt
+template<class Pad>
+word32 RSA_Decryptor<Pad>::Decrypt(const byte* cipher, word32 sz, byte* plain,
+ RandomNumberGenerator& rng)
+{
+ PK_Lengths lengths(key_.GetModulus());
+ assert(sz == lengths.FixedCiphertextLength());
+
+ if (sz != lengths.FixedCiphertextLength())
+ return 0;
+
+ ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
+ Integer x = key_.CalculateInverse(rng, Integer(cipher,
+ lengths.FixedCiphertextLength()).Ref());
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero(); // don't return false, prevents timing attack
+ x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
+ return padding_.UnPad(paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), plain);
+}
+
+
+// Private SSL type (block 1) Encrypt
+template<class Pad>
+void RSA_Decryptor<Pad>::SSL_Sign(const byte* message, word32 sz, byte* sig,
+ RandomNumberGenerator& rng)
+{
+ RSA_PublicKey inverse;
+ inverse.Initialize(key_.GetModulus(), key_.GetPrivateExponent());
+ RSA_Encryptor<RSA_BlockType1> enc(inverse); // SSL Type
+ enc.Encrypt(message, sz, sig, rng);
+}
+
+
+word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain);
+
+
+// Public SSL type (block 1) Decrypt
+template<class Pad>
+bool RSA_Encryptor<Pad>::SSL_Verify(const byte* message, word32 sz,
+ const byte* sig)
+{
+ ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength());
+ SSL_Decrypt(key_, sig, plain.get_buffer());
+
+ if ( (memcmp(plain.get_buffer(), message, sz)) == 0)
+ return true;
+ return false;
+}
+
+
+typedef RSA_Encryptor<> RSAES_Encryptor;
+typedef RSA_Decryptor<> RSAES_Decryptor;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RSA_HPP
diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp
new file mode 100644
index 00000000000..e2c04af44f4
--- /dev/null
+++ b/extra/yassl/taocrypt/include/runtime.hpp
@@ -0,0 +1,72 @@
+/* runtime.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* runtime.hpp provides C++ runtime support functions when building a pure C
+ * version of yaSSL, user must define YASSL_PURE_C
+*/
+
+
+
+#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__)
+
+#define yaSSL_NEW_HPP
+
+#if __GNUC__ > 2
+
+#include <cstdlib>
+
+
+static void* operator new (size_t sz)
+{
+ return malloc (sz ? sz : 1);
+}
+
+static void* operator new[](size_t sz)
+{
+ return malloc (sz ? sz : 1);
+}
+
+static void operator delete (void* ptr)
+{
+ if (ptr) free(ptr);
+}
+
+static void operator delete[] (void* ptr)
+{
+ if (ptr) free(ptr);
+}
+
+
+extern "C" {
+#include <assert.h>
+
+static int __cxa_pure_virtual()
+{
+ // oops, pure virtual called!
+ assert("Pure virtual method called." == "Aborted");
+ return 0;
+}
+
+} // extern "C"
+
+#endif // __GNUC__ > 2
+#endif // yaSSL_NEW_HPP && __GNUC__
+
diff --git a/extra/yassl/taocrypt/include/sha.hpp b/extra/yassl/taocrypt/include/sha.hpp
new file mode 100644
index 00000000000..b75d9e3f670
--- /dev/null
+++ b/extra/yassl/taocrypt/include/sha.hpp
@@ -0,0 +1,65 @@
+/* sha.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* sha.hpp provides SHA-1 digests, see RFC 3174
+*/
+
+#ifndef TAO_CRYPT_SHA_HPP
+#define TAO_CRYPT_SHA_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// SHA-1 digest
+class SHA : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes
+ SHA() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ void Init();
+
+ SHA(const SHA&);
+ SHA& operator= (const SHA&);
+
+ void Swap(SHA&);
+private:
+ void Transform();
+};
+
+
+inline void swap(SHA& a, SHA& b)
+{
+ a.Swap(b);
+}
+
+} // namespace
+
+
+#endif // TAO_CRYPT_SHA_HPP
+
diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am
new file mode 100644
index 00000000000..b00e6081c23
--- /dev/null
+++ b/extra/yassl/taocrypt/src/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I../include -I../../mySTL
+
+noinst_LIBRARIES = libtaocrypt.a
+libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \
+ coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp integer.cpp \
+ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp
+EXTRA_DIST = ../include/*.hpp
diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp
new file mode 100644
index 00000000000..d09a40e1578
--- /dev/null
+++ b/extra/yassl/taocrypt/src/aes.cpp
@@ -0,0 +1,401 @@
+/* aes.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's aes.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "aes.hpp"
+#include "stdexcept.hpp"
+
+
+namespace TaoCrypt {
+
+
+void AES::Process(byte* out, const byte* in, word32 sz)
+{
+ if (mode_ == ECB)
+ ECB_Process(out, in, sz);
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ CBC_Encrypt(out, in, sz);
+ else
+ CBC_Decrypt(out, in, sz);
+}
+
+
+
+void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
+{
+ assert( (keylen == 16) || (keylen == 24) || (keylen == 32) );
+
+ rounds_ = keylen/4 + 6;
+ key_.New(4*(rounds_+1));
+
+ word32 temp, *rk = key_.get_buffer();
+ unsigned int i=0;
+
+ GetUserKey(BigEndianOrder, rk, keylen/4, userKey, keylen);
+
+ switch(keylen)
+ {
+ case 16:
+ while (true)
+ {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10)
+ break;
+ rk += 4;
+ }
+ break;
+
+ case 24:
+ while (true) // for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack
+ {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8)
+ break;
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ break;
+
+ case 32:
+ while (true)
+ {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7)
+ break;
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te4[GETBYTE(temp, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 0)] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+
+ rk += 8;
+ }
+ break;
+ }
+
+ if (dir_ == DECRYPTION)
+ {
+ unsigned int i, j;
+ rk = key_.get_buffer();
+
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*rounds_; i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ // apply the inverse MixColumn transform to all round keys but the
+ // first and the last:
+ for (i = 1; i < rounds_; i++) {
+ rk += 4;
+ rk[0] =
+ Td0[Te4[GETBYTE(rk[0], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[0], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[0], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[0], 0)] & 0xff];
+ rk[1] =
+ Td0[Te4[GETBYTE(rk[1], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[1], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[1], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[1], 0)] & 0xff];
+ rk[2] =
+ Td0[Te4[GETBYTE(rk[2], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[2], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[2], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[2], 0)] & 0xff];
+ rk[3] =
+ Td0[Te4[GETBYTE(rk[3], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[3], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[3], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[3], 0)] & 0xff];
+ }
+ }
+}
+
+
+typedef BlockGetAndPut<word32, BigEndian> gpBlock;
+
+void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
+{
+ if (dir_ == ENCRYPTION)
+ encrypt(in, xOr, out);
+ else
+ decrypt(in, xOr, out);
+}
+
+
+void AES::encrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const word32 *rk = key_.get_buffer();
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ /*
+ * Nr - 1 full rounds:
+ */
+ unsigned int r = rounds_ >> 1;
+ for (;;) {
+ t0 =
+ Te0[GETBYTE(s0, 3)] ^
+ Te1[GETBYTE(s1, 2)] ^
+ Te2[GETBYTE(s2, 1)] ^
+ Te3[GETBYTE(s3, 0)] ^
+ rk[4];
+ t1 =
+ Te0[GETBYTE(s1, 3)] ^
+ Te1[GETBYTE(s2, 2)] ^
+ Te2[GETBYTE(s3, 1)] ^
+ Te3[GETBYTE(s0, 0)] ^
+ rk[5];
+ t2 =
+ Te0[GETBYTE(s2, 3)] ^
+ Te1[GETBYTE(s3, 2)] ^
+ Te2[GETBYTE(s0, 1)] ^
+ Te3[GETBYTE(s1, 0)] ^
+ rk[6];
+ t3 =
+ Te0[GETBYTE(s3, 3)] ^
+ Te1[GETBYTE(s0, 2)] ^
+ Te2[GETBYTE(s1, 1)] ^
+ Te3[GETBYTE(s2, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te0[GETBYTE(t0, 3)] ^
+ Te1[GETBYTE(t1, 2)] ^
+ Te2[GETBYTE(t2, 1)] ^
+ Te3[GETBYTE(t3, 0)] ^
+ rk[0];
+ s1 =
+ Te0[GETBYTE(t1, 3)] ^
+ Te1[GETBYTE(t2, 2)] ^
+ Te2[GETBYTE(t3, 1)] ^
+ Te3[GETBYTE(t0, 0)] ^
+ rk[1];
+ s2 =
+ Te0[GETBYTE(t2, 3)] ^
+ Te1[GETBYTE(t3, 2)] ^
+ Te2[GETBYTE(t0, 1)] ^
+ Te3[GETBYTE(t1, 0)] ^
+ rk[2];
+ s3 =
+ Te0[GETBYTE(t3, 3)] ^
+ Te1[GETBYTE(t0, 2)] ^
+ Te2[GETBYTE(t1, 1)] ^
+ Te3[GETBYTE(t2, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+
+ s0 =
+ (Te4[GETBYTE(t0, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Te4[GETBYTE(t1, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Te4[GETBYTE(t2, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Te4[GETBYTE(t3, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[3];
+
+ gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+
+}
+
+
+void AES::decrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const word32* rk = key_.get_buffer();
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ /*
+ * Nr - 1 full rounds:
+ */
+ unsigned int r = rounds_ >> 1;
+ for (;;) {
+ t0 =
+ Td0[GETBYTE(s0, 3)] ^
+ Td1[GETBYTE(s3, 2)] ^
+ Td2[GETBYTE(s2, 1)] ^
+ Td3[GETBYTE(s1, 0)] ^
+ rk[4];
+ t1 =
+ Td0[GETBYTE(s1, 3)] ^
+ Td1[GETBYTE(s0, 2)] ^
+ Td2[GETBYTE(s3, 1)] ^
+ Td3[GETBYTE(s2, 0)] ^
+ rk[5];
+ t2 =
+ Td0[GETBYTE(s2, 3)] ^
+ Td1[GETBYTE(s1, 2)] ^
+ Td2[GETBYTE(s0, 1)] ^
+ Td3[GETBYTE(s3, 0)] ^
+ rk[6];
+ t3 =
+ Td0[GETBYTE(s3, 3)] ^
+ Td1[GETBYTE(s2, 2)] ^
+ Td2[GETBYTE(s1, 1)] ^
+ Td3[GETBYTE(s0, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Td0[GETBYTE(t0, 3)] ^
+ Td1[GETBYTE(t3, 2)] ^
+ Td2[GETBYTE(t2, 1)] ^
+ Td3[GETBYTE(t1, 0)] ^
+ rk[0];
+ s1 =
+ Td0[GETBYTE(t1, 3)] ^
+ Td1[GETBYTE(t0, 2)] ^
+ Td2[GETBYTE(t3, 1)] ^
+ Td3[GETBYTE(t2, 0)] ^
+ rk[1];
+ s2 =
+ Td0[GETBYTE(t2, 3)] ^
+ Td1[GETBYTE(t1, 2)] ^
+ Td2[GETBYTE(t0, 1)] ^
+ Td3[GETBYTE(t3, 0)] ^
+ rk[2];
+ s3 =
+ Td0[GETBYTE(t3, 3)] ^
+ Td1[GETBYTE(t2, 2)] ^
+ Td2[GETBYTE(t1, 1)] ^
+ Td3[GETBYTE(t0, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[GETBYTE(t0, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Td4[GETBYTE(t1, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Td4[GETBYTE(t2, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Td4[GETBYTE(t3, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[3];
+
+ gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+}
+
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp
new file mode 100644
index 00000000000..7ba25bc9ffb
--- /dev/null
+++ b/extra/yassl/taocrypt/src/aestables.cpp
@@ -0,0 +1,724 @@
+/* aestables.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's aestables.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "aes.hpp"
+
+
+namespace TaoCrypt {
+
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+const word32 AES::Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+const word32 AES::Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+const word32 AES::Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+
+const word32 AES::Te3[256] = {
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+
+const word32 AES::Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+
+const word32 AES::Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+
+const word32 AES::Td1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+
+const word32 AES::Td2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+
+const word32 AES::Td3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+
+const word32 AES::Td4[256] = {
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+
+const word32 AES::rcon_[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp
new file mode 100644
index 00000000000..1924be9b618
--- /dev/null
+++ b/extra/yassl/taocrypt/src/algebra.cpp
@@ -0,0 +1,354 @@
+/* algebra.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's algebra.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "algebra.hpp"
+#include "integer.hpp"
+#include "vector.hpp" // mySTL::vector (simple)
+
+
+namespace TaoCrypt {
+
+template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
+{
+ return Add(a, a);
+}
+
+template <class T> const T& AbstractGroup<T>::Subtract(const Element &a,
+ const Element &b) const
+{
+ // make copy of a in case Inverse() overwrites it
+ Element a1(a);
+ return Add(a1, Inverse(b));
+}
+
+template <class T> T& AbstractGroup<T>::Accumulate(Element &a,
+ const Element &b) const
+{
+ return a = Add(a, b);
+}
+
+template <class T> T& AbstractGroup<T>::Reduce(Element &a,
+ const Element &b) const
+{
+ return a = Subtract(a, b);
+}
+
+template <class T> const T& AbstractRing<T>::Square(const Element &a) const
+{
+ return Multiply(a, a);
+}
+
+template <class T> const T& AbstractRing<T>::Divide(const Element &a,
+ const Element &b) const
+{
+ // make copy of a in case MultiplicativeInverse() overwrites it
+ Element a1(a);
+ return Multiply(a1, MultiplicativeInverse(b));
+}
+
+template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a,
+ const Element &b) const
+{
+ Element q;
+ DivisionAlgorithm(result, q, a, b);
+ return result;
+}
+
+template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a,
+ const Element &b) const
+{
+ Element g[3]={b, a};
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!Equal(g[i1], this->Identity()))
+ {
+ g[i2] = Mod(g[i0], g[i1]);
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return result = g[i0];
+}
+
+template <class T> const typename
+ QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(
+ const Element &a) const
+{
+ Element g[3]={m_modulus, a};
+#ifdef __BCPLUSPLUS__
+ // BC++50 workaround
+ Element v[3];
+ v[0]=m_domain.Identity();
+ v[1]=m_domain.MultiplicativeIdentity();
+#else
+ Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
+#endif
+ Element y;
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!Equal(g[i1], Identity()))
+ {
+ // y = g[i0] / g[i1];
+ // g[i2] = g[i0] % g[i1];
+ m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
+ // v[i2] = v[i0] - (v[i1] * y);
+ v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) :
+ m_domain.Identity();
+}
+
+template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base,
+ const Integer &exponent) const
+{
+ Element result;
+ SimultaneousMultiply(&result, base, &exponent, 1);
+ return result;
+}
+
+template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x,
+ const Integer &e1, const Element &y, const Integer &e2) const
+{
+ const unsigned expLen = max(e1.BitCount(), e2.BitCount());
+ if (expLen==0)
+ return Identity();
+
+ const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
+ const unsigned tableSize = 1<<w;
+ mySTL::vector<Element> powerTable(tableSize << w);
+
+ powerTable[1] = x;
+ powerTable[tableSize] = y;
+ if (w==1)
+ powerTable[3] = Add(x,y);
+ else
+ {
+ powerTable[2] = Double(x);
+ powerTable[2*tableSize] = Double(y);
+
+ unsigned i, j;
+
+ for (i=3; i<tableSize; i+=2)
+ powerTable[i] = Add(powerTable[i-2], powerTable[2]);
+ for (i=1; i<tableSize; i+=2)
+ for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
+ powerTable[j] = Add(powerTable[j-tableSize], y);
+
+ for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
+ powerTable[i] = Add(powerTable[i-2*tableSize],
+ powerTable[2*tableSize]);
+ for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
+ for (j=i+2; j<i+tableSize; j+=2)
+ powerTable[j] = Add(powerTable[j-1], x);
+ }
+
+ Element result;
+ unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
+ bool firstTime = true;
+
+ for (int i = expLen-1; i>=0; i--)
+ {
+ power1 = 2*power1 + e1.GetBit(i);
+ power2 = 2*power2 + e2.GetBit(i);
+
+ if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
+ {
+ unsigned squaresBefore = prevPosition-i;
+ unsigned squaresAfter = 0;
+ prevPosition = i;
+ while ((power1 || power2) && power1%2 == 0 && power2%2==0)
+ {
+ power1 /= 2;
+ power2 /= 2;
+ squaresBefore--;
+ squaresAfter++;
+ }
+ if (firstTime)
+ {
+ result = powerTable[(power2<<w) + power1];
+ firstTime = false;
+ }
+ else
+ {
+ while (squaresBefore--)
+ result = Double(result);
+ if (power1 || power2)
+ Accumulate(result, powerTable[(power2<<w) + power1]);
+ }
+ while (squaresAfter--)
+ result = Double(result);
+ power1 = power2 = 0;
+ }
+ }
+ return result;
+}
+
+
+struct WindowSlider
+{
+ WindowSlider(const Integer &exp, bool fastNegate,
+ unsigned int windowSizeIn=0)
+ : exp(exp), windowModulus(Integer::One()), windowSize(windowSizeIn),
+ windowBegin(0), fastNegate(fastNegate), firstTime(true),
+ finished(false)
+ {
+ if (windowSize == 0)
+ {
+ unsigned int expLen = exp.BitCount();
+ windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 :
+ (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 :
+ (expLen <= 1434 ? 6 : 7)))));
+ }
+ windowModulus <<= windowSize;
+ }
+
+ void FindNextWindow()
+ {
+ unsigned int expLen = exp.WordCount() * WORD_BITS;
+ unsigned int skipCount = firstTime ? 0 : windowSize;
+ firstTime = false;
+ while (!exp.GetBit(skipCount))
+ {
+ if (skipCount >= expLen)
+ {
+ finished = true;
+ return;
+ }
+ skipCount++;
+ }
+
+ exp >>= skipCount;
+ windowBegin += skipCount;
+ expWindow = exp % (1 << windowSize);
+
+ if (fastNegate && exp.GetBit(windowSize))
+ {
+ negateNext = true;
+ expWindow = (1 << windowSize) - expWindow;
+ exp += windowModulus;
+ }
+ else
+ negateNext = false;
+ }
+
+ Integer exp, windowModulus;
+ unsigned int windowSize, windowBegin, expWindow;
+ bool fastNegate, negateNext, firstTime, finished;
+};
+
+template <class T>
+void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base,
+ const Integer *expBegin, unsigned int expCount) const
+{
+ mySTL::vector<mySTL::vector<Element> > buckets(expCount);
+ mySTL::vector<WindowSlider> exponents;
+ exponents.reserve(expCount);
+ unsigned int i;
+
+ for (i=0; i<expCount; i++)
+ {
+ assert(expBegin->NotNegative());
+ exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
+ exponents[i].FindNextWindow();
+ buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
+ }
+
+ unsigned int expBitPosition = 0;
+ Element g = base;
+ bool notDone = true;
+
+ while (notDone)
+ {
+ notDone = false;
+ for (i=0; i<expCount; i++)
+ {
+ if (!exponents[i].finished && expBitPosition ==
+ exponents[i].windowBegin)
+ {
+ Element &bucket = buckets[i][exponents[i].expWindow/2];
+ if (exponents[i].negateNext)
+ Accumulate(bucket, Inverse(g));
+ else
+ Accumulate(bucket, g);
+ exponents[i].FindNextWindow();
+ }
+ notDone = notDone || !exponents[i].finished;
+ }
+
+ if (notDone)
+ {
+ g = Double(g);
+ expBitPosition++;
+ }
+ }
+
+ for (i=0; i<expCount; i++)
+ {
+ Element &r = *results++;
+ r = buckets[i][buckets[i].size()-1];
+ if (buckets[i].size() > 1)
+ {
+ for (int j = buckets[i].size()-2; j >= 1; j--)
+ {
+ Accumulate(buckets[i][j], buckets[i][j+1]);
+ Accumulate(r, buckets[i][j]);
+ }
+ Accumulate(buckets[i][0], buckets[i][1]);
+ r = Add(Double(r), buckets[i][0]);
+ }
+ }
+}
+
+template <class T> T AbstractRing<T>::Exponentiate(const Element &base,
+ const Integer &exponent) const
+{
+ Element result;
+ SimultaneousExponentiate(&result, base, &exponent, 1);
+ return result;
+}
+
+template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x,
+ const Integer &e1, const Element &y, const Integer &e2) const
+{
+ return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(
+ x, e1, y, e2);
+}
+
+template <class Element, class Iterator> Element GeneralCascadeExponentiation(
+ const AbstractRing<Element> &ring, Iterator begin, Iterator end)
+{
+ return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(),
+ begin, end);
+}
+
+template <class T>
+void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base,
+ const Integer *exponents, unsigned int expCount) const
+{
+ MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base,
+ exponents, expCount);
+}
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp
new file mode 100644
index 00000000000..1e521b48f0c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/arc4.cpp
@@ -0,0 +1,93 @@
+/* arc4.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's arc4.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "arc4.hpp"
+
+
+namespace TaoCrypt {
+
+void ARC4::SetKey(const byte* key, word32 length)
+{
+ x_ = 1;
+ y_ = 0;
+
+ word32 i;
+
+ for (i = 0; i < STATE_SIZE; i++)
+ state_[i] = i;
+
+ word32 keyIndex = 0, stateIndex = 0;
+
+ for (i = 0; i < STATE_SIZE; i++) {
+ word32 a = state_[i];
+ stateIndex += key[keyIndex] + a;
+ stateIndex &= 0xFF;
+ state_[i] = state_[stateIndex];
+ state_[stateIndex] = a;
+
+ if (++keyIndex >= length)
+ keyIndex = 0;
+ }
+}
+
+
+// local
+namespace {
+
+inline unsigned int MakeByte(word32& x, word32& y, byte* s)
+{
+ word32 a = s[x];
+ y = (y+a) & 0xff;
+
+ word32 b = s[y];
+ s[x] = b;
+ s[y] = a;
+ x = (x+1) & 0xff;
+
+ return s[(a+b) & 0xff];
+}
+
+} // namespace
+
+
+void ARC4::Process(byte* out, const byte* in, word32 length)
+{
+ if (length == 0) return;
+
+ byte *const s = state_;
+ word32 x = x_;
+ word32 y = y_;
+
+ if (in == out)
+ while (length--)
+ *out++ ^= MakeByte(x, y, s);
+ else
+ while(length--)
+ *out++ = *in++ ^ MakeByte(x, y, s);
+ x_ = x;
+ y_ = y;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
new file mode 100644
index 00000000000..d0d22a6c61d
--- /dev/null
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -0,0 +1,1051 @@
+ /* asn.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* asn.cpp implements ASN1 BER, PublicKey, and x509v3 decoding
+*/
+
+
+#include "runtime.hpp"
+#include "asn.hpp"
+#include "file.hpp"
+#include "integer.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "dh.hpp"
+#include "md5.hpp"
+#include "md2.hpp"
+#include "sha.hpp"
+#include "coding.hpp"
+#include <time.h> // gmtime();
+#include "memory.hpp" // mySTL::auto_ptr
+
+namespace TaoCrypt {
+
+namespace { // locals
+
+
+// to the minute
+bool operator>(tm& a, tm& b)
+{
+ if (a.tm_year > b.tm_year)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon > b.tm_mon)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && a.tm_mday >b.tm_mday)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
+ a.tm_mday == b.tm_mday && a.tm_hour > b.tm_hour)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
+ a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour &&
+ a.tm_min > b.tm_min)
+ return true;
+
+ return false;
+}
+
+
+bool operator<(tm& a, tm&b)
+{
+ return !(a>b);
+}
+
+
+// like atoi but only use first byte
+word32 btoi(byte b)
+{
+ return b - 0x30;
+}
+
+
+// two byte date/time, add to value
+void GetTime(int& value, const byte* date, int& i)
+{
+ value += btoi(date[i++]) * 10;
+ value += btoi(date[i++]);
+}
+
+
+// Make sure before and after dates are valid
+bool ValidateDate(const byte* date, byte format, CertDecoder::DateType dt)
+{
+ tm certTime;
+ memset(&certTime, 0, sizeof(certTime));
+ int i = 0;
+
+ if (format == UTC_TIME) {
+ if (btoi(date[0]) >= 5)
+ certTime.tm_year = 1900;
+ else
+ certTime.tm_year = 2000;
+ }
+ else { // format == GENERALIZED_TIME
+ certTime.tm_year += btoi(date[i++]) * 1000;
+ certTime.tm_year += btoi(date[i++]) * 100;
+ }
+
+ GetTime(certTime.tm_year, date, i); certTime.tm_year -= 1900; // adjust
+ GetTime(certTime.tm_mon, date, i); certTime.tm_mon -= 1; // adjust
+ GetTime(certTime.tm_mday, date, i);
+ GetTime(certTime.tm_hour, date, i);
+ GetTime(certTime.tm_min, date, i);
+ GetTime(certTime.tm_sec, date, i);
+
+ assert(date[i] == 'Z'); // only Zulu supported for this profile
+
+ time_t ltime = time(0);
+ tm* localTime = gmtime(&ltime);
+
+ if (dt == CertDecoder::BEFORE) {
+ if (*localTime < certTime)
+ return false;
+ }
+ else
+ if (*localTime > certTime)
+ return false;
+
+ return true;
+}
+
+
+class BadCertificate {};
+
+} // local namespace
+
+
+
+// used by Integer as well
+word32 GetLength(Source& source)
+{
+ word32 length = 0;
+
+ byte b = source.next();
+ if (b >= LONG_LENGTH) {
+ word32 bytes = b & 0x7F;
+
+ while (bytes--) {
+ b = source.next();
+ length = (length << 8) | b;
+ }
+ }
+ else
+ length = b;
+
+ return length;
+}
+
+
+word32 SetLength(word32 length, byte* output)
+{
+ word32 i = 0;
+
+ if (length < LONG_LENGTH)
+ output[i++] = length;
+ else {
+ output[i++] = BytePrecision(length) | 0x80;
+
+ for (int j = BytePrecision(length); j; --j) {
+ output[i] = length >> (j - 1) * 8;
+ i++;
+ }
+ }
+ return i;
+}
+
+
+PublicKey::PublicKey(const byte* k, word32 s) : key_(0), sz_(0)
+{
+ if (s) {
+ SetSize(s);
+ SetKey(k);
+ }
+}
+
+
+void PublicKey::SetSize(word32 s)
+{
+ sz_ = s;
+ key_ = new (tc) byte[sz_];
+}
+
+
+void PublicKey::SetKey(const byte* k)
+{
+ memcpy(key_, k, sz_);
+}
+
+
+void PublicKey::AddToEnd(const byte* data, word32 len)
+{
+ mySTL::auto_ptr<byte> tmp(new (tc) byte[sz_ + len]);
+
+ memcpy(tmp.get(), key_, sz_);
+ memcpy(tmp.get() + sz_, data, len);
+
+ byte* del = 0;
+ mySTL::swap(del, key_);
+ delete[] del;
+
+ key_ = tmp.release();
+ sz_ += len;
+}
+
+
+Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h)
+ : key_(k, kSz), name_(0)
+{
+ if (n) {
+ int sz = strlen(n);
+ name_ = new (tc) char[sz + 1];
+ memcpy(name_, n, sz);
+ name_[sz] = 0;
+ }
+
+ memcpy(hash_, h, SHA::DIGEST_SIZE);
+}
+
+Signer::~Signer()
+{
+ delete[] name_;
+}
+
+
+Error BER_Decoder::GetError()
+{
+ return source_.GetError();
+}
+
+
+Integer& BER_Decoder::GetInteger(Integer& integer)
+{
+ if (!source_.GetError().What())
+ integer.Decode(source_);
+ return integer;
+}
+
+
+// Read a Sequence, return length
+word32 BER_Decoder::GetSequence()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != (SEQUENCE | CONSTRUCTED)) {
+ source_.SetError(SEQUENCE_E);
+ return 0;
+ }
+
+ return GetLength(source_);
+}
+
+
+// Read a Sequence, return length
+word32 BER_Decoder::GetSet()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != (SET | CONSTRUCTED)) {
+ source_.SetError(SET_E);
+ return 0;
+ }
+
+ return GetLength(source_);
+}
+
+
+// Read Version, return it
+word32 BER_Decoder::GetVersion()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != INTEGER) {
+ source_.SetError(INTEGER_E);
+ return 0;
+ }
+
+ b = source_.next();
+ if (b != 0x01) {
+ source_.SetError(VERSION_E);
+ return 0;
+ }
+
+ return source_.next();
+}
+
+
+// Read ExplicitVersion, return it or 0 if not there (not an error)
+word32 BER_Decoder::GetExplicitVersion()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+
+ if (b == (CONTEXT_SPECIFIC | CONSTRUCTED)) { // not an error if not here
+ source_.next();
+ return GetVersion();
+ }
+ else
+ source_.prev(); // put back
+
+ return 0;
+}
+
+
+// Decode a BER encoded RSA Private Key
+void RSA_Private_Decoder::Decode(RSA_PrivateKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+ // public
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetPublicExponent(GetInteger(Integer().Ref()));
+
+ // private
+ key.SetPrivateExponent(GetInteger(Integer().Ref()));
+ key.SetPrime1(GetInteger(Integer().Ref()));
+ key.SetPrime2(GetInteger(Integer().Ref()));
+ key.SetModPrime1PrivateExponent(GetInteger(Integer().Ref()));
+ key.SetModPrime2PrivateExponent(GetInteger(Integer().Ref()));
+ key.SetMultiplicativeInverseOfPrime2ModPrime1(GetInteger(Integer().Ref()));
+}
+
+
+void RSA_Private_Decoder::ReadHeader()
+{
+ GetSequence();
+ GetVersion();
+}
+
+
+// Decode a BER encoded DSA Private Key
+void DSA_Private_Decoder::Decode(DSA_PrivateKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+ // group parameters
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetSubGroupOrder(GetInteger(Integer().Ref()));
+ key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
+
+ // key
+ key.SetPublicPart(GetInteger(Integer().Ref()));
+ key.SetPrivatePart(GetInteger(Integer().Ref()));
+}
+
+
+void DSA_Private_Decoder::ReadHeader()
+{
+ GetSequence();
+ GetVersion();
+}
+
+
+// Decode a BER encoded RSA Public Key
+void RSA_Public_Decoder::Decode(RSA_PublicKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // public key
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetPublicExponent(GetInteger(Integer().Ref()));
+}
+
+
+void RSA_Public_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+// Decode a BER encoded DSA Public Key
+void DSA_Public_Decoder::Decode(DSA_PublicKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // group parameters
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetSubGroupOrder(GetInteger(Integer().Ref()));
+ key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
+
+ // key
+ key.SetPublicPart(GetInteger(Integer().Ref()));
+}
+
+
+void DSA_Public_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+void DH_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+// Decode a BER encoded Diffie-Hellman Key
+void DH_Decoder::Decode(DH& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // group parms
+ key.SetP(GetInteger(Integer().Ref()));
+ key.SetG(GetInteger(Integer().Ref()));
+}
+
+
+CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers)
+ : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
+ signature_(0), issuer_(0), subject_(0)
+{
+ if (decode)
+ Decode(signers);
+}
+
+
+CertDecoder::~CertDecoder()
+{
+ delete[] subject_;
+ delete[] issuer_;
+ delete[] signature_;
+}
+
+
+// process certificate header, set signature offset
+void CertDecoder::ReadHeader()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence(); // total
+ certBegin_ = source_.get_index();
+
+ sigIndex_ = GetSequence(); // this cert
+ sigIndex_ += source_.get_index();
+
+ GetExplicitVersion(); // version
+ GetInteger(Integer().Ref()); // serial number
+}
+
+
+// Decode a x509v3 Certificate
+void CertDecoder::Decode(SignerList* signers)
+{
+ if (source_.GetError().What()) return;
+ DecodeToKey();
+ if (source_.GetError().What()) return;
+
+ if (source_.get_index() != sigIndex_)
+ source_.set_index(sigIndex_);
+
+ word32 confirmOID = GetAlgoId();
+ GetSignature();
+ if (source_.GetError().What()) return;
+
+ if ( confirmOID != signatureOID_ ) {
+ source_.SetError(SIG_OID_E);
+ return;
+ }
+
+ if ( memcmp(issuerHash_, subjectHash_, SHA::DIGEST_SIZE) == 0 ) {
+ if (!ValidateSelfSignature())
+ source_.SetError(SIG_CONFIRM_E);
+ }
+ else
+ if (!ValidateSignature(signers))
+ source_.SetError(SIG_CONFIRM_E);
+}
+
+
+void CertDecoder::DecodeToKey()
+{
+ ReadHeader();
+ signatureOID_ = GetAlgoId();
+ GetName(ISSUER);
+ GetValidity();
+ GetName(SUBJECT);
+ GetKey();
+}
+
+
+// Read public key
+void CertDecoder::GetKey()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence();
+ keyOID_ = GetAlgoId();
+
+ if (keyOID_ == RSAk) {
+ byte b = source_.next();
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return;
+ }
+ b = source_.next(); // length, future
+ b = source_.next();
+ while(b != 0)
+ b = source_.next();
+ }
+ else if (keyOID_ == DSAk)
+ ; // do nothing
+ else {
+ source_.SetError(UNKNOWN_OID_E);
+ return;
+ }
+
+ StoreKey();
+ if (keyOID_ == DSAk)
+ AddDSA();
+}
+
+
+// Save public key
+void CertDecoder::StoreKey()
+{
+ if (source_.GetError().What()) return;
+
+ word32 read = source_.get_index();
+ word32 length = GetSequence();
+
+ read = source_.get_index() - read;
+ length += read;
+
+ while (read--) source_.prev();
+
+ key_.SetSize(length);
+ key_.SetKey(source_.get_current());
+ source_.advance(length);
+}
+
+
+// DSA has public key after group
+void CertDecoder::AddDSA()
+{
+ if (source_.GetError().What()) return;
+
+ byte b = source_.next();
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return;
+ }
+ b = source_.next(); // length, future
+ b = source_.next();
+ while(b != 0)
+ b = source_.next();
+
+ word32 idx = source_.get_index();
+ b = source_.next();
+ if (b != INTEGER) {
+ source_.SetError(INTEGER_E);
+ return;
+ }
+
+ word32 length = GetLength(source_);
+ length += source_.get_index() - idx;
+
+ key_.AddToEnd(source_.get_buffer() + idx, length);
+}
+
+
+// process algo OID by summing, return it
+word32 CertDecoder::GetAlgoId()
+{
+ if (source_.GetError().What()) return 0;
+ word32 length = GetSequence();
+
+ byte b = source_.next();
+ if (b != OBJECT_IDENTIFIER) {
+ source_.SetError(OBJECT_ID_E);
+ return 0;
+ }
+
+ length = GetLength(source_);
+ word32 oid = 0;
+
+ while(length--)
+ oid += source_.next(); // just sum it up for now
+
+ if (oid != SHAwDSA && oid != DSAk) {
+ b = source_.next(); // should have NULL tag and 0
+
+ if (b != TAG_NULL) {
+ source_.SetError(TAG_NULL_E);
+ return 0;
+ }
+
+ b = source_.next();
+ if (b != 0) {
+ source_.SetError(EXPECT_0_E);
+ return 0;
+ }
+ }
+
+ return oid;
+}
+
+
+// read cert signature, store in signature_
+word32 CertDecoder::GetSignature()
+{
+ if (source_.GetError().What()) return 0;
+ byte b = source_.next();
+
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return 0;
+ }
+
+ sigLength_ = GetLength(source_);
+
+ b = source_.next();
+ if (b != 0) {
+ source_.SetError(EXPECT_0_E);
+ return 0;
+ }
+ sigLength_--;
+
+ signature_ = new (tc) byte[sigLength_];
+ memcpy(signature_, source_.get_current(), sigLength_);
+ source_.advance(sigLength_);
+
+ return sigLength_;
+}
+
+
+// read cert digest, store in signature_
+word32 CertDecoder::GetDigest()
+{
+ if (source_.GetError().What()) return 0;
+ byte b = source_.next();
+
+ if (b != OCTET_STRING) {
+ source_.SetError(OCTET_STR_E);
+ return 0;
+ }
+
+ sigLength_ = GetLength(source_);
+
+ signature_ = new (tc) byte[sigLength_];
+ memcpy(signature_, source_.get_current(), sigLength_);
+ source_.advance(sigLength_);
+
+ return sigLength_;
+}
+
+
+// process NAME, either issuer or subject
+void CertDecoder::GetName(NameType nt)
+{
+ if (source_.GetError().What()) return;
+
+ SHA sha;
+ word32 length = GetSequence(); // length of all distinguished names
+ length += source_.get_index();
+
+ while (source_.get_index() < length) {
+ GetSet();
+ GetSequence();
+
+ byte b = source_.next();
+ if (b != OBJECT_IDENTIFIER) {
+ source_.SetError(OBJECT_ID_E);
+ return;
+ }
+
+ word32 oidSz = GetLength(source_);
+ byte joint[2];
+ memcpy(joint, source_.get_current(), sizeof(joint));
+
+ // v1 name types
+ if (joint[0] == 0x55 && joint[1] == 0x04) {
+ source_.advance(2);
+ byte id = source_.next();
+ b = source_.next(); // strType
+ word32 strLen = GetLength(source_);
+
+ if (id == COMMON_NAME) {
+ char*& ptr = (nt == ISSUER) ? issuer_ : subject_;
+ ptr = new (tc) char[strLen + 1];
+ memcpy(ptr, source_.get_current(), strLen);
+ ptr[strLen] = 0;
+ }
+ sha.Update(source_.get_current(), strLen);
+ source_.advance(strLen);
+ }
+ else {
+ // skip
+ source_.advance(oidSz + 1);
+ word32 length = GetLength(source_);
+ source_.advance(length);
+ }
+ }
+ if (nt == ISSUER)
+ sha.Final(issuerHash_);
+ else
+ sha.Final(subjectHash_);
+}
+
+
+// process a Date, either BEFORE or AFTER
+void CertDecoder::GetDate(DateType dt)
+{
+ if (source_.GetError().What()) return;
+
+ byte b = source_.next();
+ if (b != UTC_TIME && b != GENERALIZED_TIME) {
+ source_.SetError(TIME_E);
+ return;
+ }
+
+ word32 length = GetLength(source_);
+ byte date[MAX_DATE_SZ];
+ if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) {
+ source_.SetError(DATE_SZ_E);
+ return;
+ }
+
+ memcpy(date, source_.get_current(), length);
+ source_.advance(length);
+
+ if (!ValidateDate(date, b, dt))
+ if (dt == BEFORE)
+ source_.SetError(BEFORE_DATE_E);
+ else
+ source_.SetError(AFTER_DATE_E);
+}
+
+
+void CertDecoder::GetValidity()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence();
+ GetDate(BEFORE);
+ GetDate(AFTER);
+}
+
+
+bool CertDecoder::ValidateSelfSignature()
+{
+ Source pub(key_.GetKey(), key_.size());
+ return ConfirmSignature(pub);
+}
+
+
+// extract compare signature hash from plain and place into digest
+void CertDecoder::GetCompareHash(const byte* plain, word32 sz, byte* digest,
+ word32 digSz)
+{
+ if (source_.GetError().What()) return;
+
+ Source s(plain, sz);
+ CertDecoder dec(s, false);
+
+ dec.GetSequence();
+ dec.GetAlgoId();
+ dec.GetDigest();
+
+ if (dec.sigLength_ > digSz) {
+ source_.SetError(SIG_LEN_E);
+ return;
+ }
+
+ memcpy(digest, dec.signature_, dec.sigLength_);
+}
+
+
+// validate signature signed by someone else
+bool CertDecoder::ValidateSignature(SignerList* signers)
+{
+ assert(signers);
+
+ SignerList::iterator first = signers->begin();
+ SignerList::iterator last = signers->end();
+
+ while (first != last) {
+ if ( memcmp(issuerHash_, (*first)->GetHash(), SHA::DIGEST_SIZE) == 0) {
+
+ const PublicKey& iKey = (*first)->GetPublicKey();
+ Source pub(iKey.GetKey(), iKey.size());
+ return ConfirmSignature(pub);
+ }
+ ++first;
+ }
+ return false;
+}
+
+
+// RSA confirm
+bool CertDecoder::ConfirmSignature(Source& pub)
+{
+ HashType ht;
+ mySTL::auto_ptr<HASH> hasher;
+
+ if (signatureOID_ == MD5wRSA) {
+ hasher.reset(new (tc) MD5);
+ ht = MD5h;
+ }
+ else if (signatureOID_ == MD2wRSA) {
+ hasher.reset(new (tc) MD2);
+ ht = MD2h;
+ }
+ else if (signatureOID_ == SHAwRSA || signatureOID_ == SHAwDSA) {
+ hasher.reset(new (tc) SHA);
+ ht = SHAh;
+ }
+ else {
+ source_.SetError(UNKOWN_SIG_E);
+ return false;
+ }
+
+ byte digest[SHA::DIGEST_SIZE]; // largest size
+
+ hasher->Update(source_.get_buffer() + certBegin_, sigIndex_ - certBegin_);
+ hasher->Final(digest);
+
+ if (keyOID_ == RSAk) {
+ // put in ASN.1 signature format
+ Source build;
+ Signature_Encoder(digest, hasher->getDigestSize(), ht, build);
+
+ RSA_PublicKey pubKey(pub);
+ RSAES_Encryptor enc(pubKey);
+
+ return enc.SSL_Verify(build.get_buffer(), build.size(), signature_);
+ }
+ else { // DSA
+ // extract r and s from sequence
+ byte seqDecoded[DSA_SIG_SZ];
+ DecodeDSA_Signature(seqDecoded, signature_, sigLength_);
+
+ DSA_PublicKey pubKey(pub);
+ DSA_Verifier ver(pubKey);
+
+ return ver.Verify(digest, seqDecoded);
+ }
+}
+
+
+Signature_Encoder::Signature_Encoder(const byte* dig, word32 digSz,
+ HashType digOID, Source& source)
+{
+ // build bottom up
+
+ // Digest
+ byte digArray[MAX_DIGEST_SZ];
+ word32 digestSz = SetDigest(dig, digSz, digArray);
+
+ // AlgoID
+ byte algoArray[MAX_ALGO_SZ];
+ word32 algoSz = SetAlgoID(digOID, algoArray);
+
+ // Sequence
+ byte seqArray[MAX_SEQ_SZ];
+ word32 seqSz = SetSequence(digestSz + algoSz, seqArray);
+
+ source.grow(seqSz + algoSz + digestSz); // make sure enough room
+ source.add(seqArray, seqSz);
+ source.add(algoArray, algoSz);
+ source.add(digArray, digestSz);
+}
+
+
+
+word32 Signature_Encoder::SetDigest(const byte* d, word32 dSz, byte* output)
+{
+ output[0] = OCTET_STRING;
+ output[1] = dSz;
+ memcpy(&output[2], d, dSz);
+
+ return dSz + 2;
+}
+
+
+
+word32 DER_Encoder::SetAlgoID(HashType aOID, byte* output)
+{
+ // adding TAG_NULL and 0 to end
+ static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00 };
+ static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00 };
+ static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x02, 0x05, 0x00};
+
+ int algoSz = 0;
+ const byte* algoName = 0;
+
+ switch (aOID) {
+ case SHAh:
+ algoSz = sizeof(shaAlgoID);
+ algoName = shaAlgoID;
+ break;
+
+ case MD2h:
+ algoSz = sizeof(md2AlgoID);
+ algoName = md2AlgoID;
+ break;
+
+ case MD5h:
+ algoSz = sizeof(md5AlgoID);
+ algoName = md5AlgoID;
+ break;
+
+ default:
+ error_.SetError(UNKOWN_HASH_E);
+ return 0;
+ }
+
+
+ byte ID_Length[MAX_LENGTH_SZ];
+ word32 idSz = SetLength(algoSz - 2, ID_Length); // don't include TAG_NULL/0
+
+ byte seqArray[MAX_SEQ_SZ + 1]; // add object_id to end
+ word32 seqSz = SetSequence(idSz + algoSz + 1, seqArray);
+ seqArray[seqSz++] = OBJECT_IDENTIFIER;
+
+ memcpy(output, seqArray, seqSz);
+ memcpy(output + seqSz, ID_Length, idSz);
+ memcpy(output + seqSz + idSz, algoName, algoSz);
+
+ return seqSz + idSz + algoSz;
+}
+
+
+word32 SetSequence(word32 len, byte* output)
+{
+
+ output[0] = SEQUENCE | CONSTRUCTED;
+ return SetLength(len, output + 1) + 1;
+}
+
+
+word32 EncodeDSA_Signature(const byte* signature, byte* output)
+{
+ Integer r(signature, 20);
+ Integer s(signature + 20, 20);
+
+ return EncodeDSA_Signature(r, s, output);
+}
+
+
+word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output)
+{
+ word32 rSz = r.ByteCount();
+ word32 sSz = s.ByteCount();
+
+ byte rLen[MAX_LENGTH_SZ + 1];
+ byte sLen[MAX_LENGTH_SZ + 1];
+
+ rLen[0] = INTEGER;
+ sLen[0] = INTEGER;
+
+ word32 rLenSz = SetLength(rSz, &rLen[1]) + 1;
+ word32 sLenSz = SetLength(sSz, &sLen[1]) + 1;
+
+ byte seqArray[MAX_SEQ_SZ];
+
+ word32 seqSz = SetSequence(rLenSz + rSz + sLenSz + sSz, seqArray);
+
+ // seq
+ memcpy(output, seqArray, seqSz);
+ // r
+ memcpy(output + seqSz, rLen, rLenSz);
+ r.Encode(output + seqSz + rLenSz, rSz);
+ // s
+ memcpy(output + seqSz + rLenSz + rSz, sLen, sLenSz);
+ s.Encode(output + seqSz + rLenSz + rSz + sLenSz, sSz);
+
+ return seqSz + rLenSz + rSz + sLenSz + sSz;
+}
+
+
+// put sequence encoded dsa signature into decoded in 2 20 byte integers
+word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz)
+{
+ Source source(encoded, sz);
+
+ if (source.next() != (SEQUENCE | CONSTRUCTED)) {
+ source.SetError(SEQUENCE_E);
+ return 0;
+ }
+
+ GetLength(source); // total
+
+ // r
+ if (source.next() != INTEGER) {
+ source.SetError(INTEGER_E);
+ return 0;
+ }
+ word32 rLen = GetLength(source);
+ if (rLen != 20)
+ if (rLen == 21) { // zero at front, eat
+ source.next();
+ --rLen;
+ }
+ else if (rLen == 19) { // add zero to front so 20 bytes
+ decoded[0] = 0;
+ decoded++;
+ }
+ else {
+ source.SetError(DSA_SZ_E);
+ return 0;
+ }
+ memcpy(decoded, source.get_buffer() + source.get_index(), rLen);
+ source.advance(rLen);
+
+ // s
+ if (source.next() != INTEGER) {
+ source.SetError(INTEGER_E);
+ return 0;
+ }
+ word32 sLen = GetLength(source);
+ if (sLen != 20)
+ if (sLen == 21) {
+ source.next(); // zero at front, eat
+ --sLen;
+ }
+ else if (sLen == 19) {
+ decoded[rLen] = 0; // add zero to front so 20 bytes
+ decoded++;
+ }
+ else {
+ source.SetError(DSA_SZ_E);
+ return 0;
+ }
+ memcpy(decoded + rLen, source.get_buffer() + source.get_index(), sLen);
+ source.advance(sLen);
+
+ return 40;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp
new file mode 100644
index 00000000000..944a47c288e
--- /dev/null
+++ b/extra/yassl/taocrypt/src/coding.cpp
@@ -0,0 +1,250 @@
+/* coding.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* coding.cpp implements hex and base64 encoding/decoing
+*/
+
+#include "runtime.hpp"
+#include "coding.hpp"
+#include "file.hpp"
+
+
+namespace TaoCrypt {
+
+
+namespace { // locals
+
+const byte bad = 0xFF; // invalid encoding
+
+const byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ bad, bad, bad, bad, bad, bad, bad,
+ 10, 11, 12, 13, 14, 15
+ }; // A starts at 0x41 not 0x3A
+
+
+const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/'
+ };
+
+const byte base64Decode[] = { 62, bad, bad, bad, 63, // + starts at 0x2B
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ bad, bad, bad, bad, bad, bad, bad,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25,
+ bad, bad, bad, bad, bad, bad,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51
+ };
+
+const byte pad = '=';
+const int pemLineSz = 64;
+
+} // local namespace
+
+
+// Hex Encode
+void HexEncoder::Encode()
+{
+ word32 bytes = plain_.size();
+ encoded_.New(bytes * 2);
+
+ word32 i = 0;
+
+ while (bytes--) {
+ byte p = plain_.next();
+
+ byte b = p >> 4;
+ byte b2 = p & 0xF;
+
+ encoded_[i++] = hexEncode[b];
+ encoded_[i++] = hexEncode[b2];
+ }
+
+ plain_.reset(encoded_);
+}
+
+
+// Hex Decode
+void HexDecoder::Decode()
+{
+ word32 bytes = coded_.size();
+ assert((bytes % 2) == 0);
+ decoded_.New(bytes / 2);
+
+ word32 i(0);
+
+ while (bytes) {
+ byte b = coded_.next() - 0x30; // 0 starts at 0x30
+ byte b2 = coded_.next() - 0x30;
+
+ // sanity checks
+ assert( b < sizeof(hexDecode)/sizeof(hexDecode[0]) );
+ assert( b2 < sizeof(hexDecode)/sizeof(hexDecode[0]) );
+ assert( b != bad && b2 != bad );
+
+ b = hexDecode[b];
+ b2 = hexDecode[b2];
+
+ decoded_[i++] = (b << 4) | b2;
+ bytes -= 2;
+ }
+
+ coded_.reset(decoded_);
+}
+
+
+// Base 64 Encode
+void Base64Encoder::Encode()
+{
+ word32 bytes = plain_.size();
+ word32 outSz = bytes * 4 / 3;
+ outSz += (outSz % 4); // 4 byte integrals
+
+ outSz += outSz / pemLineSz + ( (outSz % pemLineSz) ? 1 : 0); // new lines
+ encoded_.New(outSz);
+
+ word32 i = 0;
+ word32 j = 0;
+
+ while (bytes > 2) {
+ byte b1 = plain_.next();
+ byte b2 = plain_.next();
+ byte b3 = plain_.next();
+
+ // encoded idx
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
+ byte e4 = b3 & 0x3F;
+
+ // store
+ encoded_[i++] = base64Encode[e1];
+ encoded_[i++] = base64Encode[e2];
+ encoded_[i++] = base64Encode[e3];
+ encoded_[i++] = base64Encode[e4];
+
+ bytes -= 3;
+
+ if ((++j % 16) == 0)
+ encoded_[i++] = '\n';
+ }
+
+ // last integral
+ if (bytes) {
+ bool twoBytes = (bytes == 2);
+
+ byte b1 = plain_.next();
+ byte b2 = (twoBytes) ? plain_.next() : 0;
+
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = (b2 & 0xF) << 2;
+
+ encoded_[i++] = base64Encode[e1];
+ encoded_[i++] = base64Encode[e2];
+ encoded_[i++] = (twoBytes) ? base64Encode[e3] : pad;
+ encoded_[i++] = pad;
+ }
+
+ encoded_[i++] = '\n';
+ assert(i == outSz);
+
+ plain_.reset(encoded_);
+}
+
+
+// Base 64 Decode
+void Base64Decoder::Decode()
+{
+ word32 bytes = coded_.size();
+ word32 plainSz = bytes - (bytes / pemLineSz + ( (bytes % pemLineSz) ?
+ 1 : 0));
+ plainSz = plainSz * 3 / 4 + (( (plainSz * 3) % 4) ? 1 : 0);
+ decoded_.New(plainSz);
+
+ word32 i = 0;
+ word32 j = 0;
+
+ while (bytes > 3) {
+ byte e1 = coded_.next();
+ byte e2 = coded_.next();
+ byte e3 = coded_.next();
+ byte e4 = coded_.next();
+
+ // do asserts first
+ if (e1 == 0) // end file 0's
+ break;
+
+ bool pad3 = false;
+ bool pad4 = false;
+ if (e3 == pad)
+ pad3 = true;
+ if (e4 == pad)
+ pad4 = true;
+
+ e1 = base64Decode[e1 - 0x2B];
+ e2 = base64Decode[e2 - 0x2B];
+ e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B];
+ e4 = (e4 == pad) ? 0 : base64Decode[e4 - 0x2B];
+
+ byte b1 = (e1 << 2) | (e2 >> 4);
+ byte b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
+ byte b3 = ((e3 & 0x3) << 6) | e4;
+
+ decoded_[i++] = b1;
+ if (!pad3)
+ decoded_[i++] = b2;
+ if (!pad4)
+ decoded_[i++] = b3;
+ else
+ break;
+
+ bytes -= 4;
+ if ((++j % 16) == 0) {
+ byte endLine = coded_.next();
+ bytes--;
+ if (endLine == '\r') {
+ endLine = coded_.next();
+ bytes--;
+ }
+ assert(endLine == '\n');
+ }
+ }
+
+ if (i != decoded_.size())
+ decoded_.resize(i);
+ coded_.reset(decoded_);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp
new file mode 100644
index 00000000000..e5d3331500c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/des.cpp
@@ -0,0 +1,435 @@
+/* des.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's des.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "des.hpp"
+#include <string.h>
+#include "algorithm.hpp" // mySTL::swap
+
+
+namespace TaoCrypt {
+
+
+/* permuted choice table (key) */
+static const byte pc1[] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+/* number left rotations of pc1 */
+static const byte totrot[] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+};
+
+/* permuted choice key (table) */
+static const byte pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/* End of DES-defined tables */
+
+/* bit 0 is left-most in byte */
+static const int bytebit[] = {
+ 0200,0100,040,020,010,04,02,01
+};
+
+
+void DES::SetKey(const byte* key, word32 /*length*/, CipherDir dir)
+{
+ byte buffer[56+56+8];
+ byte *const pc1m = buffer; /* place to modify pc1 into */
+ byte *const pcr = pc1m + 56; /* place to rotate pc1 into */
+ byte *const ks = pcr + 56;
+ register int i,j,l;
+ int m;
+
+ for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */
+ l = pc1[j] - 1; /* integer bit location */
+ m = l & 07; /* find bit */
+ pc1m[j] = (key[l >> 3] & /* find which key byte l is in */
+ bytebit[m]) /* and which bit of that byte */
+ ? 1 : 0; /* and store 1-bit result */
+ }
+ for (i = 0; i < 16; i++) { /* key chunk for each iteration */
+ memset(ks, 0, 8); /* Clear key schedule */
+ for (j = 0; j < 56; j++) /* rotate pc1 the right amount */
+ pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28];
+ /* rotate left and right halves independently */
+ for (j = 0; j < 48; j++){ /* select bits individually */
+ /* check bit that goes to ks[j] */
+ if (pcr[pc2[j] - 1]){
+ /* mask it in if it's there */
+ l= j % 6;
+ ks[j/6] |= bytebit[l] >> 2;
+ }
+ }
+ /* Now convert to odd/even interleaved form for use in F */
+ k_[2*i] = ((word32)ks[0] << 24)
+ | ((word32)ks[2] << 16)
+ | ((word32)ks[4] << 8)
+ | ((word32)ks[6]);
+ k_[2*i + 1] = ((word32)ks[1] << 24)
+ | ((word32)ks[3] << 16)
+ | ((word32)ks[5] << 8)
+ | ((word32)ks[7]);
+ }
+
+ // reverse key schedule order
+ if (dir == DECRYPTION)
+ for (i = 0; i < 16; i += 2) {
+ mySTL::swap(k_[i], k_[32 - 2 - i]);
+ mySTL::swap(k_[i+1], k_[32 - 1 - i]);
+ }
+
+}
+
+static inline void IPERM(word32& left, word32& right)
+{
+ word32 work;
+
+ right = rotlFixed(right, 4U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ left ^= work;
+ right = rotrFixed(right^work, 20U);
+ work = (left ^ right) & 0xffff0000;
+ left ^= work;
+ right = rotrFixed(right^work, 18U);
+ work = (left ^ right) & 0x33333333;
+ left ^= work;
+ right = rotrFixed(right^work, 6U);
+ work = (left ^ right) & 0x00ff00ff;
+ left ^= work;
+ right = rotlFixed(right^work, 9U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left = rotlFixed(left^work, 1U);
+ right ^= work;
+}
+
+static inline void FPERM(word32& left, word32& right)
+{
+ word32 work;
+
+ right = rotrFixed(right, 1U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ right ^= work;
+ left = rotrFixed(left^work, 9U);
+ work = (left ^ right) & 0x00ff00ff;
+ right ^= work;
+ left = rotlFixed(left^work, 6U);
+ work = (left ^ right) & 0x33333333;
+ right ^= work;
+ left = rotlFixed(left^work, 18U);
+ work = (left ^ right) & 0xffff0000;
+ right ^= work;
+ left = rotlFixed(left^work, 20U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ right ^= work;
+ left = rotrFixed(left^work, 4U);
+}
+
+const word32 Spbox[DES::BOXES][DES::BOX_SIZE] = {
+{
+0x01010400,0x00000000,0x00010000,0x01010404,
+0x01010004,0x00010404,0x00000004,0x00010000,
+0x00000400,0x01010400,0x01010404,0x00000400,
+0x01000404,0x01010004,0x01000000,0x00000004,
+0x00000404,0x01000400,0x01000400,0x00010400,
+0x00010400,0x01010000,0x01010000,0x01000404,
+0x00010004,0x01000004,0x01000004,0x00010004,
+0x00000000,0x00000404,0x00010404,0x01000000,
+0x00010000,0x01010404,0x00000004,0x01010000,
+0x01010400,0x01000000,0x01000000,0x00000400,
+0x01010004,0x00010000,0x00010400,0x01000004,
+0x00000400,0x00000004,0x01000404,0x00010404,
+0x01010404,0x00010004,0x01010000,0x01000404,
+0x01000004,0x00000404,0x00010404,0x01010400,
+0x00000404,0x01000400,0x01000400,0x00000000,
+0x00010004,0x00010400,0x00000000,0x01010004},
+{
+0x80108020,0x80008000,0x00008000,0x00108020,
+0x00100000,0x00000020,0x80100020,0x80008020,
+0x80000020,0x80108020,0x80108000,0x80000000,
+0x80008000,0x00100000,0x00000020,0x80100020,
+0x00108000,0x00100020,0x80008020,0x00000000,
+0x80000000,0x00008000,0x00108020,0x80100000,
+0x00100020,0x80000020,0x00000000,0x00108000,
+0x00008020,0x80108000,0x80100000,0x00008020,
+0x00000000,0x00108020,0x80100020,0x00100000,
+0x80008020,0x80100000,0x80108000,0x00008000,
+0x80100000,0x80008000,0x00000020,0x80108020,
+0x00108020,0x00000020,0x00008000,0x80000000,
+0x00008020,0x80108000,0x00100000,0x80000020,
+0x00100020,0x80008020,0x80000020,0x00100020,
+0x00108000,0x00000000,0x80008000,0x00008020,
+0x80000000,0x80100020,0x80108020,0x00108000},
+{
+0x00000208,0x08020200,0x00000000,0x08020008,
+0x08000200,0x00000000,0x00020208,0x08000200,
+0x00020008,0x08000008,0x08000008,0x00020000,
+0x08020208,0x00020008,0x08020000,0x00000208,
+0x08000000,0x00000008,0x08020200,0x00000200,
+0x00020200,0x08020000,0x08020008,0x00020208,
+0x08000208,0x00020200,0x00020000,0x08000208,
+0x00000008,0x08020208,0x00000200,0x08000000,
+0x08020200,0x08000000,0x00020008,0x00000208,
+0x00020000,0x08020200,0x08000200,0x00000000,
+0x00000200,0x00020008,0x08020208,0x08000200,
+0x08000008,0x00000200,0x00000000,0x08020008,
+0x08000208,0x00020000,0x08000000,0x08020208,
+0x00000008,0x00020208,0x00020200,0x08000008,
+0x08020000,0x08000208,0x00000208,0x08020000,
+0x00020208,0x00000008,0x08020008,0x00020200},
+{
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802080,0x00800081,0x00800001,0x00002001,
+0x00000000,0x00802000,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00800080,0x00800001,
+0x00000001,0x00002000,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002001,0x00002080,
+0x00800081,0x00000001,0x00002080,0x00800080,
+0x00002000,0x00802080,0x00802081,0x00000081,
+0x00800080,0x00800001,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00000000,0x00802000,
+0x00002080,0x00800080,0x00800081,0x00000001,
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802081,0x00000081,0x00000001,0x00002000,
+0x00800001,0x00002001,0x00802080,0x00800081,
+0x00002001,0x00002080,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002000,0x00802080},
+{
+0x00000100,0x02080100,0x02080000,0x42000100,
+0x00080000,0x00000100,0x40000000,0x02080000,
+0x40080100,0x00080000,0x02000100,0x40080100,
+0x42000100,0x42080000,0x00080100,0x40000000,
+0x02000000,0x40080000,0x40080000,0x00000000,
+0x40000100,0x42080100,0x42080100,0x02000100,
+0x42080000,0x40000100,0x00000000,0x42000000,
+0x02080100,0x02000000,0x42000000,0x00080100,
+0x00080000,0x42000100,0x00000100,0x02000000,
+0x40000000,0x02080000,0x42000100,0x40080100,
+0x02000100,0x40000000,0x42080000,0x02080100,
+0x40080100,0x00000100,0x02000000,0x42080000,
+0x42080100,0x00080100,0x42000000,0x42080100,
+0x02080000,0x00000000,0x40080000,0x42000000,
+0x00080100,0x02000100,0x40000100,0x00080000,
+0x00000000,0x40080000,0x02080100,0x40000100},
+{
+0x20000010,0x20400000,0x00004000,0x20404010,
+0x20400000,0x00000010,0x20404010,0x00400000,
+0x20004000,0x00404010,0x00400000,0x20000010,
+0x00400010,0x20004000,0x20000000,0x00004010,
+0x00000000,0x00400010,0x20004010,0x00004000,
+0x00404000,0x20004010,0x00000010,0x20400010,
+0x20400010,0x00000000,0x00404010,0x20404000,
+0x00004010,0x00404000,0x20404000,0x20000000,
+0x20004000,0x00000010,0x20400010,0x00404000,
+0x20404010,0x00400000,0x00004010,0x20000010,
+0x00400000,0x20004000,0x20000000,0x00004010,
+0x20000010,0x20404010,0x00404000,0x20400000,
+0x00404010,0x20404000,0x00000000,0x20400010,
+0x00000010,0x00004000,0x20400000,0x00404010,
+0x00004000,0x00400010,0x20004010,0x00000000,
+0x20404000,0x20000000,0x00400010,0x20004010},
+{
+0x00200000,0x04200002,0x04000802,0x00000000,
+0x00000800,0x04000802,0x00200802,0x04200800,
+0x04200802,0x00200000,0x00000000,0x04000002,
+0x00000002,0x04000000,0x04200002,0x00000802,
+0x04000800,0x00200802,0x00200002,0x04000800,
+0x04000002,0x04200000,0x04200800,0x00200002,
+0x04200000,0x00000800,0x00000802,0x04200802,
+0x00200800,0x00000002,0x04000000,0x00200800,
+0x04000000,0x00200800,0x00200000,0x04000802,
+0x04000802,0x04200002,0x04200002,0x00000002,
+0x00200002,0x04000000,0x04000800,0x00200000,
+0x04200800,0x00000802,0x00200802,0x04200800,
+0x00000802,0x04000002,0x04200802,0x04200000,
+0x00200800,0x00000000,0x00000002,0x04200802,
+0x00000000,0x00200802,0x04200000,0x00000800,
+0x04000002,0x04000800,0x00000800,0x00200002},
+{
+0x10001040,0x00001000,0x00040000,0x10041040,
+0x10000000,0x10001040,0x00000040,0x10000000,
+0x00040040,0x10040000,0x10041040,0x00041000,
+0x10041000,0x00041040,0x00001000,0x00000040,
+0x10040000,0x10000040,0x10001000,0x00001040,
+0x00041000,0x00040040,0x10040040,0x10041000,
+0x00001040,0x00000000,0x00000000,0x10040040,
+0x10000040,0x10001000,0x00041040,0x00040000,
+0x00041040,0x00040000,0x10041000,0x00001000,
+0x00000040,0x10040040,0x00001000,0x00041040,
+0x10001000,0x00000040,0x10000040,0x10040000,
+0x10040040,0x10000000,0x00040000,0x10001040,
+0x00000000,0x10041040,0x00040040,0x10000040,
+0x10040000,0x10001000,0x10001040,0x00000000,
+0x10041040,0x00041000,0x00041000,0x00001040,
+0x00001040,0x00040040,0x10000000,0x10041000}
+};
+
+
+
+void DES::RawProcessBlock(word32& lIn, word32& rIn) const
+{
+ word32 l = lIn, r = rIn;
+ const word32* kptr = k_;
+
+ for (unsigned i=0; i<8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ lIn = l; rIn = r;
+}
+
+
+void DES_BASE::Process(byte* out, const byte* in, word32 sz)
+{
+ if (mode_ == ECB)
+ ECB_Process(out, in, sz);
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ CBC_Encrypt(out, in, sz);
+ else
+ CBC_Decrypt(out, in, sz);
+}
+
+
+
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+
+void DES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+
+ const word32* kptr = k_;
+
+ for (unsigned i = 0; i < 8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+void DES_EDE2::SetKey(const byte* key, word32 sz, CipherDir dir)
+{
+ des1_.SetKey(key, sz, dir);
+ des2_.SetKey(key + 8, sz, ReverseDir(dir));
+}
+
+
+void DES_EDE2::ProcessAndXorBlock(const byte* in, const byte* xOr,
+ byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+ des1_.RawProcessBlock(l, r);
+ des2_.RawProcessBlock(r, l);
+ des1_.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+void DES_EDE3::SetKey(const byte* key, word32 sz, CipherDir dir)
+{
+ des1_.SetKey(key+(dir==ENCRYPTION?0:2*8), sz, dir);
+ des2_.SetKey(key+8, sz, ReverseDir(dir));
+ des3_.SetKey(key+(dir==DECRYPTION?0:2*8), sz, dir);
+}
+
+void DES_EDE3::ProcessAndXorBlock(const byte* in, const byte* xOr,
+ byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+ des1_.RawProcessBlock(l, r);
+ des2_.RawProcessBlock(r, l);
+ des3_.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp
new file mode 100644
index 00000000000..e5a6a562c52
--- /dev/null
+++ b/extra/yassl/taocrypt/src/dh.cpp
@@ -0,0 +1,85 @@
+/* dh.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* dh.cpp implements Diffie-Hellman support
+*/
+
+#include "runtime.hpp"
+#include "dh.hpp"
+#include "asn.hpp"
+#include <cmath>
+
+namespace TaoCrypt {
+
+
+// Generate a DH Key Pair
+void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub)
+{
+ GeneratePrivate(rng, priv);
+ GeneratePublic(priv, pub);
+}
+
+
+// Generate private value
+void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv)
+{
+ Integer x(rng, Integer::One(), p_ - 1);
+ x.Encode(priv, p_.ByteCount());
+}
+
+
+// Generate public value
+void DH::GeneratePublic(const byte* priv, byte* pub)
+{
+ const word32 bc(p_.ByteCount());
+ Integer x(priv, bc);
+ Integer y(a_exp_b_mod_c(g_, x, p_));
+ y.Encode(pub, bc);
+}
+
+
+// Generate Agreement
+void DH::Agree(byte* agree, const byte* priv, const byte* otherPub)
+{
+ const word32 bc(p_.ByteCount());
+ Integer x(priv, bc);
+ Integer y(otherPub, bc);
+
+ Integer z(a_exp_b_mod_c(y, x, p_));
+ z.Encode(agree, bc);
+}
+
+
+DH::DH(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DH::Initialize(Source& source)
+{
+ DH_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/dsa.cpp b/extra/yassl/taocrypt/src/dsa.cpp
new file mode 100644
index 00000000000..4716ebb22df
--- /dev/null
+++ b/extra/yassl/taocrypt/src/dsa.cpp
@@ -0,0 +1,277 @@
+/* dsa.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "runtime.hpp"
+#include "dsa.hpp"
+#include "sha.hpp"
+#include "asn.hpp"
+#include "modarith.hpp"
+#include "stdexcept.hpp"
+
+#include "algebra.cpp" // for GCC 3.2 on aix ?
+
+
+namespace TaoCrypt {
+
+
+void DSA_PublicKey::Swap(DSA_PublicKey& other)
+{
+ p_.Swap(other.p_);
+ q_.Swap(other.q_);
+ g_.Swap(other.g_);
+ y_.Swap(other.y_);
+}
+
+
+DSA_PublicKey::DSA_PublicKey(const DSA_PublicKey& other)
+ : p_(other.p_), q_(other.q_), g_(other.g_), y_(other.y_)
+{}
+
+
+DSA_PublicKey& DSA_PublicKey::operator=(const DSA_PublicKey& that)
+{
+ DSA_PublicKey tmp(that);
+ Swap(tmp);
+ return *this;
+}
+
+
+DSA_PublicKey::DSA_PublicKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DSA_PublicKey::Initialize(Source& source)
+{
+ DSA_Public_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void DSA_PublicKey::Initialize(const Integer& p, const Integer& q,
+ const Integer& g, const Integer& y)
+{
+ p_ = p;
+ q_ = q;
+ g_ = g;
+ y_ = y;
+}
+
+
+const Integer& DSA_PublicKey::GetModulus() const
+{
+ return p_;
+}
+
+const Integer& DSA_PublicKey::GetSubGroupOrder() const
+{
+ return q_;
+}
+
+
+const Integer& DSA_PublicKey::GetSubGroupGenerator() const
+{
+ return g_;
+}
+
+
+const Integer& DSA_PublicKey::GetPublicPart() const
+{
+ return y_;
+}
+
+
+void DSA_PublicKey::SetModulus(const Integer& p)
+{
+ p_ = p;
+}
+
+
+void DSA_PublicKey::SetSubGroupOrder(const Integer& q)
+{
+ q_ = q;
+}
+
+
+void DSA_PublicKey::SetSubGroupGenerator(const Integer& g)
+{
+ g_ = g;
+}
+
+
+void DSA_PublicKey::SetPublicPart(const Integer& y)
+{
+ y_ = y;
+}
+
+
+word32 DSA_PublicKey::SignatureLength() const
+{
+ return GetSubGroupOrder().ByteCount() * 2; // r and s
+}
+
+
+
+DSA_PrivateKey::DSA_PrivateKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DSA_PrivateKey::Initialize(Source& source)
+{
+ DSA_Private_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void DSA_PrivateKey::Initialize(const Integer& p, const Integer& q,
+ const Integer& g, const Integer& y,
+ const Integer& x)
+{
+ DSA_PublicKey::Initialize(p, q, g, y);
+ x_ = x;
+}
+
+
+const Integer& DSA_PrivateKey::GetPrivatePart() const
+{
+ return x_;
+}
+
+
+void DSA_PrivateKey::SetPrivatePart(const Integer& x)
+{
+ x_ = x;
+}
+
+
+DSA_Signer::DSA_Signer(const DSA_PrivateKey& key)
+ : key_(key)
+{}
+
+
+word32 DSA_Signer::Sign(const byte* sha_digest, byte* sig,
+ RandomNumberGenerator& rng)
+{
+ const Integer& p = key_.GetModulus();
+ const Integer& q = key_.GetSubGroupOrder();
+ const Integer& g = key_.GetSubGroupGenerator();
+ const Integer& x = key_.GetPrivatePart();
+
+ Integer k(rng, 1, q - 1);
+
+ r_ = a_exp_b_mod_c(g, k, p);
+ r_ %= q;
+
+ Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m)
+
+ Integer kInv = k.InverseMod(q);
+ s_ = (kInv * (H + x*r_)) % q;
+
+ assert(!!r_ && !!s_);
+
+ int rSz = r_.ByteCount();
+
+ if (rSz == 19) {
+ sig[0] = 0;
+ sig++;
+ }
+
+ r_.Encode(sig, rSz);
+
+ int sSz = s_.ByteCount();
+
+ if (sSz == 19) {
+ sig[rSz] = 0;
+ sig++;
+ }
+
+ s_.Encode(sig + rSz, sSz);
+
+ return 40;
+}
+
+
+DSA_Verifier::DSA_Verifier(const DSA_PublicKey& key)
+ : key_(key)
+{}
+
+
+bool DSA_Verifier::Verify(const byte* sha_digest, const byte* sig)
+{
+ const Integer& p = key_.GetModulus();
+ const Integer& q = key_.GetSubGroupOrder();
+ const Integer& g = key_.GetSubGroupGenerator();
+ const Integer& y = key_.GetPublicPart();
+
+ int sz = q.ByteCount();
+
+ r_.Decode(sig, sz);
+ s_.Decode(sig + sz, sz);
+
+ if (r_ >= q || r_ < 1 || s_ >= q || s_ < 1)
+ return false;
+
+ Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m)
+
+ Integer w = s_.InverseMod(q);
+ Integer u1 = (H * w) % q;
+ Integer u2 = (r_ * w) % q;
+
+ // verify r == ((g^u1 * y^u2) mod p) mod q
+ ModularArithmetic ma(p);
+ Integer v = ma.CascadeExponentiate(g, u1, y, u2);
+ v %= q;
+
+ return r_ == v;
+}
+
+
+
+
+const Integer& DSA_Signer::GetR() const
+{
+ return r_;
+}
+
+
+const Integer& DSA_Signer::GetS() const
+{
+ return s_;
+}
+
+
+const Integer& DSA_Verifier::GetR() const
+{
+ return r_;
+}
+
+
+const Integer& DSA_Verifier::GetS() const
+{
+ return s_;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/file.cpp b/extra/yassl/taocrypt/src/file.cpp
new file mode 100644
index 00000000000..4d48b9e7bca
--- /dev/null
+++ b/extra/yassl/taocrypt/src/file.cpp
@@ -0,0 +1,118 @@
+/* file.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* file.cpp implements File Sources and Sinks
+*/
+
+#include "runtime.hpp"
+#include "file.hpp"
+
+
+namespace TaoCrypt {
+
+
+FileSource::FileSource(const char* fname, Source& source)
+{
+ file_ = fopen(fname, "rb");
+ if (file_) get(source);
+}
+
+
+FileSource::~FileSource()
+{
+ if (file_)
+ fclose(file_);
+}
+
+
+
+// return size of source from beginning or current position
+word32 FileSource::size(bool use_current)
+{
+ long current = ftell(file_);
+ long begin = current;
+
+ if (!use_current) {
+ fseek(file_, 0, SEEK_SET);
+ begin = ftell(file_);
+ }
+
+ fseek(file_, 0, SEEK_END);
+ long end = ftell(file_);
+
+ fseek(file_, current, SEEK_SET);
+
+ return end - begin;
+}
+
+
+word32 FileSource::size_left()
+{
+ return size(true);
+}
+
+
+// fill file source from source
+word32 FileSource::get(Source& source)
+{
+ word32 sz(size());
+ if (source.size() < sz)
+ source.grow(sz);
+
+ size_t bytes = fread(source.buffer_.get_buffer(), 1, sz, file_);
+
+ if (bytes == 1)
+ return sz;
+ else
+ return 0;
+}
+
+
+FileSink::FileSink(const char* fname, Source& source)
+{
+ file_ = fopen(fname, "wb");
+ if (file_) put(source);
+}
+
+
+FileSink::~FileSink()
+{
+ if (file_)
+ fclose(file_);
+}
+
+
+// fill source from file sink
+void FileSink::put(Source& source)
+{
+ fwrite(source.get_buffer(), 1, source.size(), file_);
+}
+
+
+// swap with other and reset to beginning
+void Source::reset(ByteBlock& otherBlock)
+{
+ buffer_.Swap(otherBlock);
+ current_ = 0;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/hash.cpp b/extra/yassl/taocrypt/src/hash.cpp
new file mode 100644
index 00000000000..09b9fe52b2b
--- /dev/null
+++ b/extra/yassl/taocrypt/src/hash.cpp
@@ -0,0 +1,88 @@
+/* hash.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* hash.cpp implements a base for digest types
+*/
+
+#include "runtime.hpp"
+#include <string.h>
+
+#include "hash.hpp"
+
+
+namespace TaoCrypt {
+
+
+// Update digest with data of size len, do in blocks
+void HASHwithTransform::Update(const byte* data, word32 len)
+{
+ // do block size increments
+ word32 blockSz = getBlockSize();
+ while (len) {
+ word32 add = min(len, blockSz - buffLen_);
+ memcpy(&buffer_[buffLen_], data, add);
+
+ buffLen_ += add;
+ data += add;
+ len -= add;
+
+ if (buffLen_ == blockSz) {
+ ByteReverseIf(buffer_, buffer_, blockSz, getByteOrder());
+ Transform();
+ }
+ }
+}
+
+
+// Final process, place digest in hash
+void HASHwithTransform::Final(byte* hash)
+{
+ word32 blockSz = getBlockSize();
+ word32 digestSz = getDigestSize();
+ word32 padSz = getPadSize();
+ ByteOrder order = getByteOrder();
+ word32 prePadLen = length_ + buffLen_ * 8; // in bits
+
+ buffer_[buffLen_++] = 0x80; // add 1
+
+ // pad with zeros
+ if (buffLen_ > padSz) {
+ while (buffLen_ < blockSz) buffer_[buffLen_++] = 0;
+ ByteReverseIf(buffer_, buffer_, blockSz, order);
+ Transform();
+ }
+ while (buffLen_ < padSz) buffer_[buffLen_++] = 0;
+
+ ByteReverseIf(buffer_, buffer_, blockSz, order);
+
+ word32 hiSize = 0; // for future 64 bit length TODO:
+ memcpy(&buffer_[padSz], order ? &hiSize : &prePadLen, sizeof(prePadLen));
+ memcpy(&buffer_[padSz+4], order ? &prePadLen : &hiSize, sizeof(prePadLen));
+
+
+ Transform();
+ ByteReverseIf(digest_, digest_, digestSz, order);
+ memcpy(hash, digest_, digestSz);
+
+ Init(); // reset state
+}
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
new file mode 100644
index 00000000000..9be0a25b363
--- /dev/null
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -0,0 +1,4181 @@
+/* integer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+/* based on Wei Dai's integer.cpp from CryptoPP */
+
+#ifdef _MSC_VER
+ // 4250: dominance
+ // 4660: explicitly instantiating a class already implicitly instantiated
+ // 4661: no suitable definition provided for explicit template request
+ // 4786: identifer was truncated in debug information
+ // 4355: 'this' : used in base member initializer list
+# pragma warning(disable: 4250 4660 4661 4786 4355)
+#endif
+
+#include "runtime.hpp"
+#include "integer.hpp"
+#include "modarith.hpp"
+#include "asn.hpp"
+#include "stdexcept.hpp"
+
+#include "algebra.cpp"
+
+
+#ifdef __DECCXX
+ #include <c_asm.h> // for asm multiply overflow
+#endif
+
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ #ifdef __GNUC__
+ #include <xmmintrin.h>
+ #include <signal.h>
+ #include <setjmp.h>
+ #ifdef TAOCRYPT_MEMALIGN_AVAILABLE
+ #include <malloc.h>
+ #else
+ #include <stdlib.h>
+ #endif
+ #else
+ #include <emmintrin.h>
+ #endif
+#elif defined(_MSC_VER) && defined(_M_IX86)
+ #pragma message("You do not seem to have the Visual C++ Processor Pack ")
+ #pragma message("installed, so use of SSE2 intrinsics will be disabled.")
+#elif defined(__GNUC__) && defined(__i386__)
+/* #warning You do not have GCC 3.3 or later, or did not specify the -msse2 \
+ compiler option. Use of SSE2 intrinsics will be disabled.
+*/
+#endif
+
+
+namespace TaoCrypt {
+
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+
+template <class T>
+CPP_TYPENAME AllocatorBase<T>::pointer AlignedAllocator<T>::allocate(
+ size_type n, const void *)
+{
+ CheckSize(n);
+ if (n == 0)
+ return 0;
+ if (n >= 4)
+ {
+ void* p;
+ #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
+ while (!(p = _mm_malloc(sizeof(T)*n, 16)))
+ #elif defined(TAOCRYPT_MEMALIGN_AVAILABLE)
+ while (!(p = memalign(16, sizeof(T)*n)))
+ #elif defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16)
+ while (!(p = malloc(sizeof(T)*n)))
+ #else
+ while (!(p = (byte *)malloc(sizeof(T)*n + 8)))
+ // assume malloc alignment is at least 8
+ #endif
+ CallNewHandler();
+
+ #ifdef TAOCRYPT_NO_ALIGNED_ALLOC
+ assert(m_pBlock == 0);
+ m_pBlock = p;
+ if (!IsAlignedOn(p, 16))
+ {
+ assert(IsAlignedOn(p, 8));
+ p = (byte *)p + 8;
+ }
+ #endif
+
+ assert(IsAlignedOn(p, 16));
+ return (T*)p;
+ }
+ return new (tc) T[n];
+}
+
+
+template <class T>
+void AlignedAllocator<T>::deallocate(void* p, size_type n)
+{
+ memset(p, 0, n*sizeof(T));
+ if (n >= 4)
+ {
+ #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
+ _mm_free(p);
+ #elif defined(TAOCRYPT_NO_ALIGNED_ALLOC)
+ assert(m_pBlock == p || (byte*)m_pBlock+8 == p);
+ free(m_pBlock);
+ m_pBlock = 0;
+ #else
+ free(p);
+ #endif
+ }
+ else
+ delete [] (T *)p;
+}
+
+#endif // SSE2
+
+
+// ******** start of integer needs
+
+// start 5.2.1 adds DWord and Word ********
+
+// ********************************************************
+
+class DWord {
+public:
+DWord() {}
+
+#ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ explicit DWord(word low)
+ {
+ whole_ = low;
+ }
+#else
+ explicit DWord(word low)
+ {
+ halfs_.low = low;
+ halfs_.high = 0;
+ }
+#endif
+
+ DWord(word low, word high)
+ {
+ halfs_.low = low;
+ halfs_.high = high;
+ }
+
+ static DWord Multiply(word a, word b)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = (dword)a * b;
+ #elif defined(__alpha__)
+ r.halfs_.low = a*b;
+ #ifdef __GNUC__
+ __asm__("umulh %1,%2,%0" : "=r" (r.halfs_.high)
+ : "r" (a), "r" (b));
+ #elif defined(__DECCXX)
+ r.halfs_.high = asm("umulh %a0, %a1, %v0", a, b);
+ #else
+ #error unsupported alpha compiler for asm multiply overflow
+ #endif
+ #elif defined(__ia64__)
+ r.halfs_.low = a*b;
+ __asm__("xmpy.hu %0=%1,%2" : "=f" (r.halfs_.high)
+ : "f" (a), "f" (b));
+ #elif defined(_ARCH_PPC64)
+ r.halfs_.low = a*b;
+ __asm__("mulhdu %0,%1,%2" : "=r" (r.halfs_.high)
+ : "r" (a), "r" (b) : "cc");
+ #elif defined(__x86_64__)
+ __asm__("mulq %3" : "=d" (r.halfs_.high), "=a" (r.halfs_.low) :
+ "a" (a), "rm" (b) : "cc");
+ #elif defined(__mips64)
+ __asm__("dmultu %2,%3" : "=h" (r.halfs_.high), "=l" (r.halfs_.low)
+ : "r" (a), "r" (b));
+ #elif defined(_M_IX86)
+ // for testing
+ word64 t = (word64)a * b;
+ r.halfs_.high = ((word32 *)(&t))[1];
+ r.halfs_.low = (word32)t;
+ #else
+ #error can not implement DWord
+ #endif
+ return r;
+ }
+
+ static DWord MultiplyAndAdd(word a, word b, word c)
+ {
+ DWord r = Multiply(a, b);
+ return r += c;
+ }
+
+ DWord & operator+=(word a)
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ whole_ = whole_ + a;
+ #else
+ halfs_.low += a;
+ halfs_.high += (halfs_.low < a);
+ #endif
+ return *this;
+ }
+
+ DWord operator+(word a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ + a;
+ #else
+ r.halfs_.low = halfs_.low + a;
+ r.halfs_.high = halfs_.high + (r.halfs_.low < a);
+ #endif
+ return r;
+ }
+
+ DWord operator-(DWord a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ - a.whole_;
+ #else
+ r.halfs_.low = halfs_.low - a.halfs_.low;
+ r.halfs_.high = halfs_.high - a.halfs_.high -
+ (r.halfs_.low > halfs_.low);
+ #endif
+ return r;
+ }
+
+ DWord operator-(word a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ - a;
+ #else
+ r.halfs_.low = halfs_.low - a;
+ r.halfs_.high = halfs_.high - (r.halfs_.low > halfs_.low);
+ #endif
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ word operator/(word divisor);
+
+ word operator%(word a);
+
+ bool operator!() const
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return !whole_;
+ #else
+ return !halfs_.high && !halfs_.low;
+ #endif
+ }
+
+ word GetLowHalf() const {return halfs_.low;}
+ word GetHighHalf() const {return halfs_.high;}
+ word GetHighHalfAsBorrow() const {return 0-halfs_.high;}
+
+private:
+ union
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ dword whole_;
+ #endif
+ struct
+ {
+ #ifdef LITTLE_ENDIAN_ORDER
+ word low;
+ word high;
+ #else
+ word high;
+ word low;
+ #endif
+ } halfs_;
+ };
+};
+
+
+class Word {
+public:
+ Word() {}
+
+ Word(word value)
+ {
+ whole_ = value;
+ }
+
+ Word(hword low, hword high)
+ {
+ whole_ = low | (word(high) << (WORD_BITS/2));
+ }
+
+ static Word Multiply(hword a, hword b)
+ {
+ Word r;
+ r.whole_ = (word)a * b;
+ return r;
+ }
+
+ Word operator-(Word a)
+ {
+ Word r;
+ r.whole_ = whole_ - a.whole_;
+ return r;
+ }
+
+ Word operator-(hword a)
+ {
+ Word r;
+ r.whole_ = whole_ - a;
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ hword operator/(hword divisor)
+ {
+ return hword(whole_ / divisor);
+ }
+
+ bool operator!() const
+ {
+ return !whole_;
+ }
+
+ word GetWhole() const {return whole_;}
+ hword GetLowHalf() const {return hword(whole_);}
+ hword GetHighHalf() const {return hword(whole_>>(WORD_BITS/2));}
+ hword GetHighHalfAsBorrow() const {return 0-hword(whole_>>(WORD_BITS/2));}
+
+private:
+ word whole_;
+};
+
+
+// dummy is VC60 compiler bug workaround
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+template <class S, class D>
+S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ // estimate the quotient: do a 2 S by 1 S divide
+ S Q;
+ if (S(B1+1) == 0)
+ Q = A[2];
+ else
+ Q = D(A[1], A[2]) / S(B1+1);
+
+ // now subtract Q*B from A
+ D p = D::Multiply(B0, Q);
+ D u = (D) A[0] - p.GetLowHalf();
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() -
+ D::Multiply(B1, Q);
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (D) A[0] - B0;
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - B1 - u.GetHighHalfAsBorrow();
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+template <class S, class D>
+inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B)
+{
+ if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ return D(Ah.GetLowHalf(), Ah.GetHighHalf());
+ else
+ {
+ S Q[2];
+ T[0] = Al.GetLowHalf();
+ T[1] = Al.GetHighHalf();
+ T[2] = Ah.GetLowHalf();
+ T[3] = Ah.GetHighHalf();
+ Q[1] = DivideThreeWordsByTwo<S, D>(T+1, B.GetLowHalf(),
+ B.GetHighHalf());
+ Q[0] = DivideThreeWordsByTwo<S, D>(T, B.GetLowHalf(), B.GetHighHalf());
+ return D(Q[0], Q[1]);
+ }
+}
+
+
+// returns quotient, which must fit in a word
+inline word DWord::operator/(word a)
+{
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return word(whole_ / a);
+ #else
+ hword r[4];
+ return DivideFourWordsByTwo<hword, Word>(r, halfs_.low,
+ halfs_.high, a).GetWhole();
+ #endif
+}
+
+inline word DWord::operator%(word a)
+{
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return word(whole_ % a);
+ #else
+ if (a < (word(1) << (WORD_BITS/2)))
+ {
+ hword h = hword(a);
+ word r = halfs_.high % h;
+ r = ((halfs_.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h;
+ return hword((hword(halfs_.low) + (r << (WORD_BITS/2))) % h);
+ }
+ else
+ {
+ hword r[4];
+ DivideFourWordsByTwo<hword, Word>(r, halfs_.low, halfs_.high, a);
+ return Word(r[0], r[1]).GetWhole();
+ }
+ #endif
+}
+
+
+
+// end 5.2.1 DWord and Word adds
+
+
+
+
+
+static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};
+
+static inline unsigned int RoundupSize(unsigned int n)
+{
+ if (n<=8)
+ return RoundupSizeTable[n];
+ else if (n<=16)
+ return 16;
+ else if (n<=32)
+ return 32;
+ else if (n<=64)
+ return 64;
+ else return 1U << BitPrecision(n-1);
+}
+
+
+template <class T>
+static Integer StringToInteger(const T *str)
+{
+ word radix;
+
+ unsigned int length;
+ for (length = 0; str[length] != 0; length++) {}
+
+ Integer v;
+
+ if (length == 0)
+ return v;
+
+ switch (str[length-1])
+ {
+ case 'h':
+ case 'H':
+ radix=16;
+ break;
+ case 'o':
+ case 'O':
+ radix=8;
+ break;
+ case 'b':
+ case 'B':
+ radix=2;
+ break;
+ default:
+ radix=10;
+ }
+
+ if (length > 2 && str[0] == '0' && str[1] == 'x')
+ radix = 16;
+
+ for (unsigned i=0; i<length; i++)
+ {
+ word digit;
+
+ if (str[i] >= '0' && str[i] <= '9')
+ digit = str[i] - '0';
+ else if (str[i] >= 'A' && str[i] <= 'F')
+ digit = str[i] - 'A' + 10;
+ else if (str[i] >= 'a' && str[i] <= 'f')
+ digit = str[i] - 'a' + 10;
+ else
+ digit = radix;
+
+ if (digit < radix)
+ {
+ v *= radix;
+ v += digit;
+ }
+ }
+
+ if (str[0] == '-')
+ v.Negate();
+
+ return v;
+}
+
+static int Compare(const word *A, const word *B, unsigned int N)
+{
+ while (N--)
+ if (A[N] > B[N])
+ return 1;
+ else if (A[N] < B[N])
+ return -1;
+
+ return 0;
+}
+
+static word Increment(word *A, unsigned int N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t+B;
+ if (A[0] >= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (++A[i])
+ return 0;
+ return 1;
+}
+
+static word Decrement(word *A, unsigned int N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t-B;
+ if (A[0] <= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (A[i]--)
+ return 0;
+ return 1;
+}
+
+static void TwosComplement(word *A, unsigned int N)
+{
+ Decrement(A, N);
+ for (unsigned i=0; i<N; i++)
+ A[i] = ~A[i];
+}
+
+
+static word LinearMultiply(word *C, const word *A, word B, unsigned int N)
+{
+ word carry=0;
+ for(unsigned i=0; i<N; i++)
+ {
+ DWord p = DWord::MultiplyAndAdd(A[i], B, carry);
+ C[i] = p.GetLowHalf();
+ carry = p.GetHighHalf();
+ }
+ return carry;
+}
+
+
+static word AtomicInverseModPower2(word A)
+{
+ assert(A%2==1);
+
+ word R=A%8;
+
+ for (unsigned i=3; i<WORD_BITS; i*=2)
+ R = R*(2-R*A);
+
+ assert(R*A==1);
+ return R;
+}
+
+
+// ********************************************************
+
+class Portable
+{
+public:
+ static word Add(word *C, const word *A, const word *B, unsigned int N);
+ static word Subtract(word *C, const word *A, const word*B, unsigned int N);
+
+ static inline void Multiply2(word *C, const word *A, const word *B);
+ static inline word Multiply2Add(word *C, const word *A, const word *B);
+ static void Multiply4(word *C, const word *A, const word *B);
+ static void Multiply8(word *C, const word *A, const word *B);
+ static inline unsigned int MultiplyRecursionLimit() {return 8;}
+
+ static inline void Multiply2Bottom(word *C, const word *A, const word *B);
+ static void Multiply4Bottom(word *C, const word *A, const word *B);
+ static void Multiply8Bottom(word *C, const word *A, const word *B);
+ static inline unsigned int MultiplyBottomRecursionLimit() {return 8;}
+
+ static void Square2(word *R, const word *A);
+ static void Square4(word *R, const word *A);
+ static void Square8(word *R, const word *A) {assert(false);}
+ static inline unsigned int SquareRecursionLimit() {return 4;}
+};
+
+word Portable::Add(word *C, const word *A, const word *B, unsigned int N)
+{
+ assert (N%2 == 0);
+
+ DWord u(0, 0);
+ for (unsigned int i = 0; i < N; i+=2)
+ {
+ u = DWord(A[i]) + B[i] + u.GetHighHalf();
+ C[i] = u.GetLowHalf();
+ u = DWord(A[i+1]) + B[i+1] + u.GetHighHalf();
+ C[i+1] = u.GetLowHalf();
+ }
+ return u.GetHighHalf();
+}
+
+word Portable::Subtract(word *C, const word *A, const word *B, unsigned int N)
+{
+ assert (N%2 == 0);
+
+ DWord u(0, 0);
+ for (unsigned int i = 0; i < N; i+=2)
+ {
+ u = (DWord) A[i] - B[i] - u.GetHighHalfAsBorrow();
+ C[i] = u.GetLowHalf();
+ u = (DWord) A[i+1] - B[i+1] - u.GetHighHalfAsBorrow();
+ C[i+1] = u.GetLowHalf();
+ }
+ return 0-u.GetHighHalf();
+}
+
+void Portable::Multiply2(word *C, const word *A, const word *B)
+{
+/*
+ word s;
+ dword d;
+
+ if (A1 >= A0)
+ if (B0 >= B1)
+ {
+ s = 0;
+ d = (dword)(A1-A0)*(B0-B1);
+ }
+ else
+ {
+ s = (A1-A0);
+ d = (dword)s*(word)(B0-B1);
+ }
+ else
+ if (B0 > B1)
+ {
+ s = (B0-B1);
+ d = (word)(A1-A0)*(dword)s;
+ }
+ else
+ {
+ s = 0;
+ d = (dword)(A0-A1)*(B1-B0);
+ }
+*/
+ // this segment is the branchless equivalent of above
+ word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
+ unsigned int ai = A[1] < A[0];
+ unsigned int bi = B[0] < B[1];
+ unsigned int di = ai & bi;
+ DWord d = DWord::Multiply(D[di], D[di+2]);
+ D[1] = D[3] = 0;
+ unsigned int si = ai + !bi;
+ word s = D[si];
+
+ DWord A0B0 = DWord::Multiply(A[0], B[0]);
+ C[0] = A0B0.GetLowHalf();
+
+ DWord A1B1 = DWord::Multiply(A[1], B[1]);
+ DWord t = (DWord) A0B0.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf()
+ + A1B1.GetLowHalf();
+ C[1] = t.GetLowHalf();
+
+ t = A1B1 + t.GetHighHalf() + A0B0.GetHighHalf() + d.GetHighHalf()
+ + A1B1.GetHighHalf() - s;
+ C[2] = t.GetLowHalf();
+ C[3] = t.GetHighHalf();
+}
+
+inline void Portable::Multiply2Bottom(word *C, const word *A, const word *B)
+{
+ DWord t = DWord::Multiply(A[0], B[0]);
+ C[0] = t.GetLowHalf();
+ C[1] = t.GetHighHalf() + A[0]*B[1] + A[1]*B[0];
+}
+
+word Portable::Multiply2Add(word *C, const word *A, const word *B)
+{
+ word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
+ unsigned int ai = A[1] < A[0];
+ unsigned int bi = B[0] < B[1];
+ unsigned int di = ai & bi;
+ DWord d = DWord::Multiply(D[di], D[di+2]);
+ D[1] = D[3] = 0;
+ unsigned int si = ai + !bi;
+ word s = D[si];
+
+ DWord A0B0 = DWord::Multiply(A[0], B[0]);
+ DWord t = A0B0 + C[0];
+ C[0] = t.GetLowHalf();
+
+ DWord A1B1 = DWord::Multiply(A[1], B[1]);
+ t = (DWord) t.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() +
+ A1B1.GetLowHalf() + C[1];
+ C[1] = t.GetLowHalf();
+
+ t = (DWord) t.GetHighHalf() + A1B1.GetLowHalf() + A0B0.GetHighHalf() +
+ d.GetHighHalf() + A1B1.GetHighHalf() - s + C[2];
+ C[2] = t.GetLowHalf();
+
+ t = (DWord) t.GetHighHalf() + A1B1.GetHighHalf() + C[3];
+ C[3] = t.GetLowHalf();
+ return t.GetHighHalf();
+}
+
+
+#define MulAcc(x, y) \
+ p = DWord::MultiplyAndAdd(A[x], B[y], c); \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+#define SaveMulAcc(s, x, y) \
+ R[s] = c; \
+ p = DWord::MultiplyAndAdd(A[x], B[y], d); \
+ c = p.GetLowHalf(); \
+ p = (DWord) e + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e = p.GetHighHalf();
+
+#define SquAcc(x, y) \
+ q = DWord::Multiply(A[x], A[y]); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf(); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+#define SaveSquAcc(s, x, y) \
+ R[s] = c; \
+ q = DWord::Multiply(A[x], A[y]); \
+ p = q + d; \
+ c = p.GetLowHalf(); \
+ p = (DWord) e + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e = p.GetHighHalf(); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+
+void Portable::Multiply4(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 3, 1);
+ MulAcc(2, 2);
+ MulAcc(1, 3);
+
+ SaveMulAcc(4, 2, 3);
+ MulAcc(3, 2);
+
+ R[5] = c;
+ p = DWord::MultiplyAndAdd(A[3], B[3], d);
+ R[6] = p.GetLowHalf();
+ R[7] = e + p.GetHighHalf();
+}
+
+void Portable::Square2(word *R, const word *A)
+{
+ DWord p, q;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], A[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ SquAcc(0, 1);
+
+ R[1] = c;
+ p = DWord::MultiplyAndAdd(A[1], A[1], d);
+ R[2] = p.GetLowHalf();
+ R[3] = e + p.GetHighHalf();
+}
+
+void Portable::Square4(word *R, const word *A)
+{
+#ifdef _MSC_VER
+ // VC60 workaround: MSVC 6.0 has an optimization bug that makes
+ // (dword)A*B where either A or B has been cast to a dword before
+ // very expensive. Revisit this function when this
+ // bug is fixed.
+ Multiply4(R, A, A);
+#else
+ const word *B = A;
+ DWord p, q;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], A[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ SquAcc(0, 1);
+
+ SaveSquAcc(1, 2, 0);
+ MulAcc(1, 1);
+
+ SaveSquAcc(2, 0, 3);
+ SquAcc(1, 2);
+
+ SaveSquAcc(3, 3, 1);
+ MulAcc(2, 2);
+
+ SaveSquAcc(4, 2, 3);
+
+ R[5] = c;
+ p = DWord::MultiplyAndAdd(A[3], A[3], d);
+ R[6] = p.GetLowHalf();
+ R[7] = e + p.GetHighHalf();
+#endif
+}
+
+void Portable::Multiply8(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 0, 4);
+ MulAcc(1, 3);
+ MulAcc(2, 2);
+ MulAcc(3, 1);
+ MulAcc(4, 0);
+
+ SaveMulAcc(4, 0, 5);
+ MulAcc(1, 4);
+ MulAcc(2, 3);
+ MulAcc(3, 2);
+ MulAcc(4, 1);
+ MulAcc(5, 0);
+
+ SaveMulAcc(5, 0, 6);
+ MulAcc(1, 5);
+ MulAcc(2, 4);
+ MulAcc(3, 3);
+ MulAcc(4, 2);
+ MulAcc(5, 1);
+ MulAcc(6, 0);
+
+ SaveMulAcc(6, 0, 7);
+ MulAcc(1, 6);
+ MulAcc(2, 5);
+ MulAcc(3, 4);
+ MulAcc(4, 3);
+ MulAcc(5, 2);
+ MulAcc(6, 1);
+ MulAcc(7, 0);
+
+ SaveMulAcc(7, 1, 7);
+ MulAcc(2, 6);
+ MulAcc(3, 5);
+ MulAcc(4, 4);
+ MulAcc(5, 3);
+ MulAcc(6, 2);
+ MulAcc(7, 1);
+
+ SaveMulAcc(8, 2, 7);
+ MulAcc(3, 6);
+ MulAcc(4, 5);
+ MulAcc(5, 4);
+ MulAcc(6, 3);
+ MulAcc(7, 2);
+
+ SaveMulAcc(9, 3, 7);
+ MulAcc(4, 6);
+ MulAcc(5, 5);
+ MulAcc(6, 4);
+ MulAcc(7, 3);
+
+ SaveMulAcc(10, 4, 7);
+ MulAcc(5, 6);
+ MulAcc(6, 5);
+ MulAcc(7, 4);
+
+ SaveMulAcc(11, 5, 7);
+ MulAcc(6, 6);
+ MulAcc(7, 5);
+
+ SaveMulAcc(12, 6, 7);
+ MulAcc(7, 6);
+
+ R[13] = c;
+ p = DWord::MultiplyAndAdd(A[7], B[7], d);
+ R[14] = p.GetLowHalf();
+ R[15] = e + p.GetHighHalf();
+}
+
+void Portable::Multiply4Bottom(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ R[2] = c;
+ R[3] = d + A[0] * B[3] + A[1] * B[2] + A[2] * B[1] + A[3] * B[0];
+}
+
+void Portable::Multiply8Bottom(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 0, 4);
+ MulAcc(1, 3);
+ MulAcc(2, 2);
+ MulAcc(3, 1);
+ MulAcc(4, 0);
+
+ SaveMulAcc(4, 0, 5);
+ MulAcc(1, 4);
+ MulAcc(2, 3);
+ MulAcc(3, 2);
+ MulAcc(4, 1);
+ MulAcc(5, 0);
+
+ SaveMulAcc(5, 0, 6);
+ MulAcc(1, 5);
+ MulAcc(2, 4);
+ MulAcc(3, 3);
+ MulAcc(4, 2);
+ MulAcc(5, 1);
+ MulAcc(6, 0);
+
+ R[6] = c;
+ R[7] = d + A[0] * B[7] + A[1] * B[6] + A[2] * B[5] + A[3] * B[4] +
+ A[4] * B[3] + A[5] * B[2] + A[6] * B[1] + A[7] * B[0];
+}
+
+
+#undef MulAcc
+#undef SaveMulAcc
+#undef SquAcc
+#undef SaveSquAcc
+
+// optimized
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+// ************** x86 feature detection ***************
+
+static bool s_sse2Enabled = true;
+
+static void CpuId(word32 input, word32 *output)
+{
+#ifdef __GNUC__
+ __asm__
+ (
+ // save ebx in case -fPIC is being used
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d"(output[3])
+ : "a" (input)
+ );
+#else
+ __asm
+ {
+ mov eax, input
+ cpuid
+ mov edi, output
+ mov [edi], eax
+ mov [edi+4], ebx
+ mov [edi+8], ecx
+ mov [edi+12], edx
+ }
+#endif
+}
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+#ifndef _MSC_VER
+static jmp_buf s_env;
+static void SigIllHandler(int)
+{
+ longjmp(s_env, 1);
+}
+#endif
+
+static bool HasSSE2()
+{
+ if (!s_sse2Enabled)
+ return false;
+
+ word32 cpuid[4];
+ CpuId(1, cpuid);
+ if ((cpuid[3] & (1 << 26)) == 0)
+ return false;
+
+#ifdef _MSC_VER
+ __try
+ {
+ __asm xorpd xmm0, xmm0 // executing SSE2 instruction
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#else
+ typedef void (*SigHandler)(int);
+
+ SigHandler oldHandler = signal(SIGILL, SigIllHandler);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_env))
+ result = false;
+ else
+ __asm __volatile ("xorps %xmm0, %xmm0");
+
+ signal(SIGILL, oldHandler);
+ return result;
+#endif
+}
+#endif
+
+static bool IsP4()
+{
+ word32 cpuid[4];
+
+ CpuId(0, cpuid);
+ mySTL::swap(cpuid[2], cpuid[3]);
+ if (memcmp(cpuid+1, "GenuineIntel", 12) != 0)
+ return false;
+
+ CpuId(1, cpuid);
+ return ((cpuid[0] >> 8) & 0xf) == 0xf;
+}
+
+// ************** Pentium/P4 optimizations ***************
+
+class PentiumOptimized : public Portable
+{
+public:
+ static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B,
+ unsigned int N);
+ static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B,
+ unsigned int N);
+ static void TAOCRYPT_CDECL Multiply4(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A,
+ const word *B);
+};
+
+class P4Optimized
+{
+public:
+ static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B,
+ unsigned int N);
+ static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B,
+ unsigned int N);
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ static void TAOCRYPT_CDECL Multiply4(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A,
+ const word *B);
+#endif
+};
+
+typedef word (TAOCRYPT_CDECL * PAddSub)(word *C, const word *A, const word *B,
+ unsigned int N);
+typedef void (TAOCRYPT_CDECL * PMul)(word *C, const word *A, const word *B);
+
+static PAddSub s_pAdd, s_pSub;
+#ifdef SSE2_INTRINSICS_AVAILABLE
+static PMul s_pMul4, s_pMul8, s_pMul8B;
+#endif
+
+static void SetPentiumFunctionPointers()
+{
+ if (IsP4())
+ {
+ s_pAdd = &P4Optimized::Add;
+ s_pSub = &P4Optimized::Subtract;
+ }
+ else
+ {
+ s_pAdd = &PentiumOptimized::Add;
+ s_pSub = &PentiumOptimized::Subtract;
+ }
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ if (HasSSE2())
+ {
+ s_pMul4 = &P4Optimized::Multiply4;
+ s_pMul8 = &P4Optimized::Multiply8;
+ s_pMul8B = &P4Optimized::Multiply8Bottom;
+ }
+ else
+ {
+ s_pMul4 = &PentiumOptimized::Multiply4;
+ s_pMul8 = &PentiumOptimized::Multiply8;
+ s_pMul8B = &PentiumOptimized::Multiply8Bottom;
+ }
+#endif
+}
+
+static const char s_RunAtStartupSetPentiumFunctionPointers =
+ (SetPentiumFunctionPointers(), 0);
+
+void DisableSSE2()
+{
+ s_sse2Enabled = false;
+ SetPentiumFunctionPointers();
+}
+
+class LowLevel : public PentiumOptimized
+{
+public:
+ inline static word Add(word *C, const word *A, const word *B,
+ unsigned int N)
+ {return s_pAdd(C, A, B, N);}
+ inline static word Subtract(word *C, const word *A, const word *B,
+ unsigned int N)
+ {return s_pSub(C, A, B, N);}
+ inline static void Square4(word *R, const word *A)
+ {Multiply4(R, A, A);}
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ inline static void Multiply4(word *C, const word *A, const word *B)
+ {s_pMul4(C, A, B);}
+ inline static void Multiply8(word *C, const word *A, const word *B)
+ {s_pMul8(C, A, B);}
+ inline static void Multiply8Bottom(word *C, const word *A, const word *B)
+ {s_pMul8B(C, A, B);}
+#endif
+};
+
+// use some tricks to share assembly code between MSVC and GCC
+#ifdef _MSC_VER
+ #define TAOCRYPT_NAKED __declspec(naked)
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+ #define AddPrologue \
+ __asm push ebp \
+ __asm push ebx \
+ __asm push esi \
+ __asm push edi \
+ __asm mov ecx, [esp+20] \
+ __asm mov edx, [esp+24] \
+ __asm mov ebx, [esp+28] \
+ __asm mov esi, [esp+32]
+ #define AddEpilogue \
+ __asm pop edi \
+ __asm pop esi \
+ __asm pop ebx \
+ __asm pop ebp \
+ __asm ret
+ #define MulPrologue \
+ __asm push ebp \
+ __asm push ebx \
+ __asm push esi \
+ __asm push edi \
+ __asm mov ecx, [esp+28] \
+ __asm mov esi, [esp+24] \
+ __asm push [esp+20]
+ #define MulEpilogue \
+ __asm add esp, 4 \
+ __asm pop edi \
+ __asm pop esi \
+ __asm pop ebx \
+ __asm pop ebp \
+ __asm ret
+#else
+ #define TAOCRYPT_NAKED
+ #define AS1(x) #x ";"
+ #define AS2(x, y) #x ", " #y ";"
+ #define AddPrologue \
+ __asm__ __volatile__ \
+ ( \
+ "push %%ebx;" /* save this manually, in case of -fPIC */ \
+ "mov %2, %%ebx;" \
+ ".intel_syntax noprefix;" \
+ "push ebp;"
+ #define AddEpilogue \
+ "pop ebp;" \
+ ".att_syntax prefix;" \
+ "pop %%ebx;" \
+ : \
+ : "c" (C), "d" (A), "m" (B), "S" (N) \
+ : "%edi", "memory", "cc" \
+ );
+ #define MulPrologue \
+ __asm__ __volatile__ \
+ ( \
+ "push %%ebx;" /* save this manually, in case of -fPIC */ \
+ "push %%ebp;" \
+ "push %0;" \
+ ".intel_syntax noprefix;"
+ #define MulEpilogue \
+ "add esp, 4;" \
+ "pop ebp;" \
+ "pop ebx;" \
+ ".att_syntax prefix;" \
+ : \
+ : "rm" (Z), "S" (X), "c" (Y) \
+ : "%eax", "%edx", "%edi", "memory", "cc" \
+ );
+#endif
+
+TAOCRYPT_NAKED word PentiumOptimized::Add(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( sub ecx, edx) // hold the distance between C & A so we
+ // can add this to A to get C
+ AS2( xor eax, eax) // clear eax
+
+ AS2( sub eax, esi) // eax is a negative index from end of B
+ AS2( lea ebx, [ebx+4*esi]) // ebx is end of B
+
+ AS2( sar eax, 1) // unit of eax is now dwords; this also
+ // clears the carry flag
+ AS1( jz loopendAdd) // if no dwords then nothing to do
+
+ AS1(loopstartAdd:)
+ AS2( mov esi,[edx]) // load lower word of A
+ AS2( mov ebp,[edx+4]) // load higher word of A
+
+ AS2( mov edi,[ebx+8*eax]) // load lower word of B
+ AS2( lea edx,[edx+8]) // advance A and C
+
+ AS2( adc esi,edi) // add lower words
+ AS2( mov edi,[ebx+8*eax+4]) // load higher word of B
+
+ AS2( adc ebp,edi) // add higher words
+ AS1( inc eax) // advance B
+
+ AS2( mov [edx+ecx-8],esi) // store lower word result
+ AS2( mov [edx+ecx-4],ebp) // store higher word result
+
+ AS1( jnz loopstartAdd) // loop until eax overflows and becomes zero
+
+ AS1(loopendAdd:)
+ AS2( adc eax, 0) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+TAOCRYPT_NAKED word PentiumOptimized::Subtract(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( sub ecx, edx) // hold the distance between C & A so we
+ // can add this to A to get C
+ AS2( xor eax, eax) // clear eax
+
+ AS2( sub eax, esi) // eax is a negative index from end of B
+ AS2( lea ebx, [ebx+4*esi]) // ebx is end of B
+
+ AS2( sar eax, 1) // unit of eax is now dwords; this also
+ // clears the carry flag
+ AS1( jz loopendSub) // if no dwords then nothing to do
+
+ AS1(loopstartSub:)
+ AS2( mov esi,[edx]) // load lower word of A
+ AS2( mov ebp,[edx+4]) // load higher word of A
+
+ AS2( mov edi,[ebx+8*eax]) // load lower word of B
+ AS2( lea edx,[edx+8]) // advance A and C
+
+ AS2( sbb esi,edi) // subtract lower words
+ AS2( mov edi,[ebx+8*eax+4]) // load higher word of B
+
+ AS2( sbb ebp,edi) // subtract higher words
+ AS1( inc eax) // advance B
+
+ AS2( mov [edx+ecx-8],esi) // store lower word result
+ AS2( mov [edx+ecx-4],ebp) // store higher word result
+
+ AS1( jnz loopstartSub) // loop until eax overflows and becomes zero
+
+ AS1(loopendSub:)
+ AS2( adc eax, 0) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+// On Pentium 4, the adc and sbb instructions are very expensive, so avoid them.
+
+TAOCRYPT_NAKED word P4Optimized::Add(word *C, const word *A, const word *B,
+ unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( xor eax, eax)
+ AS1( neg esi)
+ AS1( jz loopendAddP4) // if no dwords then nothing to do
+
+ AS2( mov edi, [edx])
+ AS2( mov ebp, [ebx])
+ AS1( jmp carry1AddP4)
+
+ AS1(loopstartAddP4:)
+ AS2( mov edi, [edx+8])
+ AS2( add ecx, 8)
+ AS2( add edx, 8)
+ AS2( mov ebp, [ebx])
+ AS2( add edi, eax)
+ AS1( jc carry1AddP4)
+ AS2( xor eax, eax)
+
+ AS1(carry1AddP4:)
+ AS2( add edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( mov [ecx], edi)
+ AS2( mov edi, [edx+4])
+ AS2( cmovc eax, ebp)
+ AS2( mov ebp, [ebx+4])
+ AS2( add ebx, 8)
+ AS2( add edi, eax)
+ AS1( jc carry2AddP4)
+ AS2( xor eax, eax)
+
+ AS1(carry2AddP4:)
+ AS2( add edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( cmovc eax, ebp)
+ AS2( mov [ecx+4], edi)
+ AS2( add esi, 2)
+ AS1( jnz loopstartAddP4)
+
+ AS1(loopendAddP4:)
+
+ AddEpilogue
+}
+
+TAOCRYPT_NAKED word P4Optimized::Subtract(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( xor eax, eax)
+ AS1( neg esi)
+ AS1( jz loopendSubP4) // if no dwords then nothing to do
+
+ AS2( mov edi, [edx])
+ AS2( mov ebp, [ebx])
+ AS1( jmp carry1SubP4)
+
+ AS1(loopstartSubP4:)
+ AS2( mov edi, [edx+8])
+ AS2( add edx, 8)
+ AS2( add ecx, 8)
+ AS2( mov ebp, [ebx])
+ AS2( sub edi, eax)
+ AS1( jc carry1SubP4)
+ AS2( xor eax, eax)
+
+ AS1(carry1SubP4:)
+ AS2( sub edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( mov [ecx], edi)
+ AS2( mov edi, [edx+4])
+ AS2( cmovc eax, ebp)
+ AS2( mov ebp, [ebx+4])
+ AS2( add ebx, 8)
+ AS2( sub edi, eax)
+ AS1( jc carry2SubP4)
+ AS2( xor eax, eax)
+
+ AS1(carry2SubP4:)
+ AS2( sub edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( cmovc eax, ebp)
+ AS2( mov [ecx+4], edi)
+ AS2( add esi, 2)
+ AS1( jnz loopstartSubP4)
+
+ AS1(loopendSubP4:)
+
+ AddEpilogue
+}
+
+// multiply assembly code originally contributed by Leonard Janke
+
+#define MulStartup \
+ AS2(xor ebp, ebp) \
+ AS2(xor edi, edi) \
+ AS2(xor ebx, ebx)
+
+#define MulShiftCarry \
+ AS2(mov ebp, edx) \
+ AS2(mov edi, ebx) \
+ AS2(xor ebx, ebx)
+
+#define MulAccumulateBottom(i,j) \
+ AS2(mov eax, [ecx+4*j]) \
+ AS2(imul eax, dword ptr [esi+4*i]) \
+ AS2(add ebp, eax)
+
+#define MulAccumulate(i,j) \
+ AS2(mov eax, [ecx+4*j]) \
+ AS1(mul dword ptr [esi+4*i]) \
+ AS2(add ebp, eax) \
+ AS2(adc edi, edx) \
+ AS2(adc bl, bh)
+
+#define MulStoreDigit(i) \
+ AS2(mov edx, edi) \
+ AS2(mov edi, [esp]) \
+ AS2(mov [edi+4*i], ebp)
+
+#define MulLastDiagonal(digits) \
+ AS2(mov eax, [ecx+4*(digits-1)]) \
+ AS1(mul dword ptr [esi+4*(digits-1)]) \
+ AS2(add ebp, eax) \
+ AS2(adc edx, edi) \
+ AS2(mov edi, [esp]) \
+ AS2(mov [edi+4*(2*digits-2)], ebp) \
+ AS2(mov [edi+4*(2*digits-1)], edx)
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply4(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulLastDiagonal(4)
+ MulEpilogue
+}
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply8(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(4,0)
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulAccumulate(0,4)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(5,0)
+ MulAccumulate(4,1)
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulAccumulate(1,4)
+ MulAccumulate(0,5)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulAccumulate(6,0)
+ MulAccumulate(5,1)
+ MulAccumulate(4,2)
+ MulAccumulate(3,3)
+ MulAccumulate(2,4)
+ MulAccumulate(1,5)
+ MulAccumulate(0,6)
+ MulStoreDigit(6)
+ MulShiftCarry
+
+ MulAccumulate(7,0)
+ MulAccumulate(6,1)
+ MulAccumulate(5,2)
+ MulAccumulate(4,3)
+ MulAccumulate(3,4)
+ MulAccumulate(2,5)
+ MulAccumulate(1,6)
+ MulAccumulate(0,7)
+ MulStoreDigit(7)
+ MulShiftCarry
+
+ MulAccumulate(7,1)
+ MulAccumulate(6,2)
+ MulAccumulate(5,3)
+ MulAccumulate(4,4)
+ MulAccumulate(3,5)
+ MulAccumulate(2,6)
+ MulAccumulate(1,7)
+ MulStoreDigit(8)
+ MulShiftCarry
+
+ MulAccumulate(7,2)
+ MulAccumulate(6,3)
+ MulAccumulate(5,4)
+ MulAccumulate(4,5)
+ MulAccumulate(3,6)
+ MulAccumulate(2,7)
+ MulStoreDigit(9)
+ MulShiftCarry
+
+ MulAccumulate(7,3)
+ MulAccumulate(6,4)
+ MulAccumulate(5,5)
+ MulAccumulate(4,6)
+ MulAccumulate(3,7)
+ MulStoreDigit(10)
+ MulShiftCarry
+
+ MulAccumulate(7,4)
+ MulAccumulate(6,5)
+ MulAccumulate(5,6)
+ MulAccumulate(4,7)
+ MulStoreDigit(11)
+ MulShiftCarry
+
+ MulAccumulate(7,5)
+ MulAccumulate(6,6)
+ MulAccumulate(5,7)
+ MulStoreDigit(12)
+ MulShiftCarry
+
+ MulAccumulate(7,6)
+ MulAccumulate(6,7)
+ MulStoreDigit(13)
+ MulShiftCarry
+
+ MulLastDiagonal(8)
+ MulEpilogue
+}
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply8Bottom(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(4,0)
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulAccumulate(0,4)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(5,0)
+ MulAccumulate(4,1)
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulAccumulate(1,4)
+ MulAccumulate(0,5)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulAccumulate(6,0)
+ MulAccumulate(5,1)
+ MulAccumulate(4,2)
+ MulAccumulate(3,3)
+ MulAccumulate(2,4)
+ MulAccumulate(1,5)
+ MulAccumulate(0,6)
+ MulStoreDigit(6)
+ MulShiftCarry
+
+ MulAccumulateBottom(7,0)
+ MulAccumulateBottom(6,1)
+ MulAccumulateBottom(5,2)
+ MulAccumulateBottom(4,3)
+ MulAccumulateBottom(3,4)
+ MulAccumulateBottom(2,5)
+ MulAccumulateBottom(1,6)
+ MulAccumulateBottom(0,7)
+ MulStoreDigit(7)
+ MulEpilogue
+}
+
+#undef AS1
+#undef AS2
+
+#else // not x86 - no processor specific code at this layer
+
+typedef Portable LowLevel;
+
+#endif
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+
+#ifdef __GNUC__
+#define TAOCRYPT_FASTCALL
+#else
+#define TAOCRYPT_FASTCALL __fastcall
+#endif
+
+static void TAOCRYPT_FASTCALL P4_Mul(__m128i *C, const __m128i *A,
+ const __m128i *B)
+{
+ __m128i a3210 = _mm_load_si128(A);
+ __m128i b3210 = _mm_load_si128(B);
+
+ __m128i sum;
+
+ __m128i z = _mm_setzero_si128();
+ __m128i a2b2_a0b0 = _mm_mul_epu32(a3210, b3210);
+ C[0] = a2b2_a0b0;
+
+ __m128i a3120 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(3, 1, 2, 0));
+ __m128i b3021 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 2, 1));
+ __m128i a1b0_a0b1 = _mm_mul_epu32(a3120, b3021);
+ __m128i a1b0 = _mm_unpackhi_epi32(a1b0_a0b1, z);
+ __m128i a0b1 = _mm_unpacklo_epi32(a1b0_a0b1, z);
+ C[1] = _mm_add_epi64(a1b0, a0b1);
+
+ __m128i a31 = _mm_srli_epi64(a3210, 32);
+ __m128i b31 = _mm_srli_epi64(b3210, 32);
+ __m128i a3b3_a1b1 = _mm_mul_epu32(a31, b31);
+ C[6] = a3b3_a1b1;
+
+ __m128i a1b1 = _mm_unpacklo_epi32(a3b3_a1b1, z);
+ __m128i b3012 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 1, 2));
+ __m128i a2b0_a0b2 = _mm_mul_epu32(a3210, b3012);
+ __m128i a0b2 = _mm_unpacklo_epi32(a2b0_a0b2, z);
+ __m128i a2b0 = _mm_unpackhi_epi32(a2b0_a0b2, z);
+ sum = _mm_add_epi64(a1b1, a0b2);
+ C[2] = _mm_add_epi64(sum, a2b0);
+
+ __m128i a2301 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i b2103 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(2, 1, 0, 3));
+ __m128i a3b0_a1b2 = _mm_mul_epu32(a2301, b3012);
+ __m128i a2b1_a0b3 = _mm_mul_epu32(a3210, b2103);
+ __m128i a3b0 = _mm_unpackhi_epi32(a3b0_a1b2, z);
+ __m128i a1b2 = _mm_unpacklo_epi32(a3b0_a1b2, z);
+ __m128i a2b1 = _mm_unpackhi_epi32(a2b1_a0b3, z);
+ __m128i a0b3 = _mm_unpacklo_epi32(a2b1_a0b3, z);
+ __m128i sum1 = _mm_add_epi64(a3b0, a1b2);
+ sum = _mm_add_epi64(a2b1, a0b3);
+ C[3] = _mm_add_epi64(sum, sum1);
+
+ __m128i a3b1_a1b3 = _mm_mul_epu32(a2301, b2103);
+ __m128i a2b2 = _mm_unpackhi_epi32(a2b2_a0b0, z);
+ __m128i a3b1 = _mm_unpackhi_epi32(a3b1_a1b3, z);
+ __m128i a1b3 = _mm_unpacklo_epi32(a3b1_a1b3, z);
+ sum = _mm_add_epi64(a2b2, a3b1);
+ C[4] = _mm_add_epi64(sum, a1b3);
+
+ __m128i a1302 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(1, 3, 0, 2));
+ __m128i b1203 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(1, 2, 0, 3));
+ __m128i a3b2_a2b3 = _mm_mul_epu32(a1302, b1203);
+ __m128i a3b2 = _mm_unpackhi_epi32(a3b2_a2b3, z);
+ __m128i a2b3 = _mm_unpacklo_epi32(a3b2_a2b3, z);
+ C[5] = _mm_add_epi64(a3b2, a2b3);
+}
+
+void P4Optimized::Multiply4(word *C, const word *A, const word *B)
+{
+ __m128i temp[7];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ C[0] = w[0];
+
+ __m64 s1, s2;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w18, w20);
+ s1 = _mm_add_si64(s1, s2);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w22, w26);
+ s1 = _mm_add_si64(s1, s2);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[7] = _mm_cvtsi64_si32(s1) + w[27];
+ _mm_empty();
+}
+
+void P4Optimized::Multiply8(word *C, const word *A, const word *B)
+{
+ __m128i temp[28];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+ const word *x = (word *)temp+7*4;
+ const __m64 *mx = (__m64 *)x;
+ const word *y = (word *)temp+7*4*2;
+ const __m64 *my = (__m64 *)y;
+ const word *z = (word *)temp+7*4*3;
+ const __m64 *mz = (__m64 *)z;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B);
+
+ P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1);
+
+ P4_Mul(temp+21, (__m128i *)A+1, (__m128i *)B+1);
+
+ C[0] = w[0];
+
+ __m64 s1, s2, s3, s4;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+ __m64 w27 = _mm_cvtsi32_si64(w[27]);
+
+ __m64 x0 = _mm_cvtsi32_si64(x[0]);
+ __m64 x1 = _mm_cvtsi32_si64(x[1]);
+ __m64 x4 = mx[2];
+ __m64 x6 = mx[3];
+ __m64 x8 = mx[4];
+ __m64 x10 = mx[5];
+ __m64 x12 = mx[6];
+ __m64 x14 = mx[7];
+ __m64 x16 = mx[8];
+ __m64 x18 = mx[9];
+ __m64 x20 = mx[10];
+ __m64 x22 = mx[11];
+ __m64 x26 = _mm_cvtsi32_si64(x[26]);
+ __m64 x27 = _mm_cvtsi32_si64(x[27]);
+
+ __m64 y0 = _mm_cvtsi32_si64(y[0]);
+ __m64 y1 = _mm_cvtsi32_si64(y[1]);
+ __m64 y4 = my[2];
+ __m64 y6 = my[3];
+ __m64 y8 = my[4];
+ __m64 y10 = my[5];
+ __m64 y12 = my[6];
+ __m64 y14 = my[7];
+ __m64 y16 = my[8];
+ __m64 y18 = my[9];
+ __m64 y20 = my[10];
+ __m64 y22 = my[11];
+ __m64 y26 = _mm_cvtsi32_si64(y[26]);
+ __m64 y27 = _mm_cvtsi32_si64(y[27]);
+
+ __m64 z0 = _mm_cvtsi32_si64(z[0]);
+ __m64 z1 = _mm_cvtsi32_si64(z[1]);
+ __m64 z4 = mz[2];
+ __m64 z6 = mz[3];
+ __m64 z8 = mz[4];
+ __m64 z10 = mz[5];
+ __m64 z12 = mz[6];
+ __m64 z14 = mz[7];
+ __m64 z16 = mz[8];
+ __m64 z18 = mz[9];
+ __m64 z20 = mz[10];
+ __m64 z22 = mz[11];
+ __m64 z26 = _mm_cvtsi32_si64(z[26]);
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x0, y0);
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s3);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x1, y1);
+ s4 = _mm_add_si64(x4, y4);
+ s1 = _mm_add_si64(s1, w18);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w20);
+ s1 = _mm_add_si64(s1, s3);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x6, y6);
+ s4 = _mm_add_si64(x8, y8);
+ s1 = _mm_add_si64(s1, w22);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w26);
+ s1 = _mm_add_si64(s1, s3);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x10, y10);
+ s4 = _mm_add_si64(x12, y12);
+ s1 = _mm_add_si64(s1, w27);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, s3);
+ C[7] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x14, y14);
+ s4 = _mm_add_si64(x16, y16);
+ s1 = _mm_add_si64(s1, z0);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, s3);
+ C[8] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x18, y18);
+ s4 = _mm_add_si64(x20, y20);
+ s1 = _mm_add_si64(s1, z1);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, z4);
+ s1 = _mm_add_si64(s1, s3);
+ C[9] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x22, y22);
+ s4 = _mm_add_si64(x26, y26);
+ s1 = _mm_add_si64(s1, z6);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, z8);
+ s1 = _mm_add_si64(s1, s3);
+ C[10] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x27, y27);
+ s1 = _mm_add_si64(s1, z10);
+ s1 = _mm_add_si64(s1, z12);
+ s1 = _mm_add_si64(s1, s3);
+ C[11] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z14, z16);
+ s1 = _mm_add_si64(s1, s3);
+ C[12] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z18, z20);
+ s1 = _mm_add_si64(s1, s3);
+ C[13] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z22, z26);
+ s1 = _mm_add_si64(s1, s3);
+ C[14] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[15] = z[27] + _mm_cvtsi64_si32(s1);
+ _mm_empty();
+}
+
+void P4Optimized::Multiply8Bottom(word *C, const word *A, const word *B)
+{
+ __m128i temp[21];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+ const word *x = (word *)temp+7*4;
+ const __m64 *mx = (__m64 *)x;
+ const word *y = (word *)temp+7*4*2;
+ const __m64 *my = (__m64 *)y;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B);
+
+ P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1);
+
+ C[0] = w[0];
+
+ __m64 s1, s2, s3, s4;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+
+ __m64 x0 = _mm_cvtsi32_si64(x[0]);
+ __m64 x1 = _mm_cvtsi32_si64(x[1]);
+ __m64 x4 = mx[2];
+ __m64 x6 = mx[3];
+ __m64 x8 = mx[4];
+
+ __m64 y0 = _mm_cvtsi32_si64(y[0]);
+ __m64 y1 = _mm_cvtsi32_si64(y[1]);
+ __m64 y4 = my[2];
+ __m64 y6 = my[3];
+ __m64 y8 = my[4];
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x0, y0);
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s3);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x1, y1);
+ s4 = _mm_add_si64(x4, y4);
+ s1 = _mm_add_si64(s1, w18);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w20);
+ s1 = _mm_add_si64(s1, s3);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x6, y6);
+ s4 = _mm_add_si64(x8, y8);
+ s1 = _mm_add_si64(s1, w22);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w26);
+ s1 = _mm_add_si64(s1, s3);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[7] = _mm_cvtsi64_si32(s1) + w[27] + x[10] + y[10] + x[12] + y[12];
+ _mm_empty();
+}
+
+#endif // #ifdef SSE2_INTRINSICS_AVAILABLE
+
+// end optimized
+
+// ********************************************************
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+//VC60 workaround: compiler bug triggered without the extra dummy parameters
+
+// R[2*N] - result = A*B
+// T[2*N] - temporary work space
+// A[N] --- multiplier
+// B[N] --- multiplicant
+
+
+void RecursiveMultiply(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (LowLevel::MultiplyRecursionLimit() >= 8 && N==8)
+ LowLevel::Multiply8(R, A, B);
+ else if (LowLevel::MultiplyRecursionLimit() >= 4 && N==4)
+ LowLevel::Multiply4(R, A, B);
+ else if (N==2)
+ LowLevel::Multiply2(R, A, B);
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ LowLevel::Subtract(R0, A0, A1, N2);
+ LowLevel::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply(R0, T2, A0, B0, N2);
+ RecursiveMultiply(R2, T2, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1),R[01] holds A0*B0, R[23] holds A1*B1
+
+ carry += LowLevel::Add(T0, T0, R0, N);
+ carry += LowLevel::Add(T0, T0, R2, N);
+ carry += LowLevel::Add(R1, R1, T0, N);
+
+ assert (carry >= 0 && carry <= 2);
+ Increment(R3, N2, carry);
+ }
+}
+
+
+void RecursiveSquare(word *R, word *T, const word *A, unsigned int N)
+{
+ assert(N && N%2==0);
+ if (LowLevel::SquareRecursionLimit() >= 8 && N==8)
+ LowLevel::Square8(R, A);
+ if (LowLevel::SquareRecursionLimit() >= 4 && N==4)
+ LowLevel::Square4(R, A);
+ else if (N==2)
+ LowLevel::Square2(R, A);
+ else
+ {
+ const unsigned int N2 = N/2;
+
+ RecursiveSquare(R0, T2, A0, N2);
+ RecursiveSquare(R2, T2, A1, N2);
+ RecursiveMultiply(T0, T2, A0, A1, N2);
+
+ word carry = LowLevel::Add(R1, R1, T0, N);
+ carry += LowLevel::Add(R1, R1, T0, N);
+ Increment(R3, N2, carry);
+ }
+}
+
+
+// R[N] - bottom half of A*B
+// T[N] - temporary work space
+// A[N] - multiplier
+// B[N] - multiplicant
+
+
+void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+ if (LowLevel::MultiplyBottomRecursionLimit() >= 8 && N==8)
+ LowLevel::Multiply8Bottom(R, A, B);
+ else if (LowLevel::MultiplyBottomRecursionLimit() >= 4 && N==4)
+ LowLevel::Multiply4Bottom(R, A, B);
+ else if (N==2)
+ LowLevel::Multiply2Bottom(R, A, B);
+ else
+ {
+ const unsigned int N2 = N/2;
+
+ RecursiveMultiply(R, T, A0, B0, N2);
+ RecursiveMultiplyBottom(T0, T1, A1, B0, N2);
+ LowLevel::Add(R1, R1, T0, N2);
+ RecursiveMultiplyBottom(T0, T1, A0, B1, N2);
+ LowLevel::Add(R1, R1, T0, N2);
+ }
+}
+
+/*
+template <class P>
+void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N, const P *dummy=0)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N==4)
+ {
+ P::Multiply4(T, A, B);
+ ((dword *)R)[0] = ((dword *)T)[2];
+ ((dword *)R)[1] = ((dword *)T)[3];
+ }
+ else if (N==2)
+ {
+ P::Multiply2(T, A, B);
+ ((dword *)R)[0] = ((dword *)T)[1];
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ P::Subtract(R0, A1, A0, N2);
+ P::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ P::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ P::Subtract(R0, A1, A0, N2);
+ P::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ P::Subtract(R0, A0, A1, N2);
+ P::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ P::Subtract(R0, A1, A0, N2);
+ P::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ P::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply<P>(T2, R0, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1
+
+ word c2 = P::Subtract(R0, L+N2, L, N2);
+ c2 += P::Subtract(R0, R0, T0, N2);
+ word t = (Compare(R0, T2, N2) == -1);
+
+ carry += t;
+ carry += Increment(R0, N2, c2+t);
+ carry += P::Add(R0, R0, T1, N2);
+ carry += P::Add(R0, R0, T3, N2);
+ assert (carry >= 0 && carry <= 2);
+
+ CopyWords(R1, T3, N2);
+ Increment(R1, N2, carry);
+ }
+}
+*/
+
+
+void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N==4)
+ {
+ LowLevel::Multiply4(T, A, B);
+ memcpy(R, T+4, 4*WORD_SIZE);
+ }
+ else if (N==2)
+ {
+ LowLevel::Multiply2(T, A, B);
+ memcpy(R, T+2, 2*WORD_SIZE);
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ LowLevel::Subtract(R0, A0, A1, N2);
+ LowLevel::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply(T2, R0, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1
+
+ word c2 = LowLevel::Subtract(R0, L+N2, L, N2);
+ c2 += LowLevel::Subtract(R0, R0, T0, N2);
+ word t = (Compare(R0, T2, N2) == -1);
+
+ carry += t;
+ carry += Increment(R0, N2, c2+t);
+ carry += LowLevel::Add(R0, R0, T1, N2);
+ carry += LowLevel::Add(R0, R0, T3, N2);
+ assert (carry >= 0 && carry <= 2);
+
+ CopyWords(R1, T3, N2);
+ Increment(R1, N2, carry);
+ }
+}
+
+
+inline word Add(word *C, const word *A, const word *B, unsigned int N)
+{
+ return LowLevel::Add(C, A, B, N);
+}
+
+inline word Subtract(word *C, const word *A, const word *B, unsigned int N)
+{
+ return LowLevel::Subtract(C, A, B, N);
+}
+
+inline void Multiply(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ RecursiveMultiply(R, T, A, B, N);
+}
+
+inline void Square(word *R, word *T, const word *A, unsigned int N)
+{
+ RecursiveSquare(R, T, A, N);
+}
+
+
+void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA,
+ const word *B, unsigned int NB)
+{
+ if (NA == NB)
+ {
+ if (A == B)
+ Square(R, T, A, NA);
+ else
+ Multiply(R, T, A, B, NA);
+
+ return;
+ }
+
+ if (NA > NB)
+ {
+ mySTL::swap(A, B);
+ mySTL::swap(NA, NB);
+ }
+
+ assert(NB % NA == 0);
+ assert((NB/NA)%2 == 0); // NB is an even multiple of NA
+
+ if (NA==2 && !A[1])
+ {
+ switch (A[0])
+ {
+ case 0:
+ SetWords(R, 0, NB+2);
+ return;
+ case 1:
+ CopyWords(R, B, NB);
+ R[NB] = R[NB+1] = 0;
+ return;
+ default:
+ R[NB] = LinearMultiply(R, B, A[0], NB);
+ R[NB+1] = 0;
+ return;
+ }
+ }
+
+ Multiply(R, T, A, B, NA);
+ CopyWords(T+2*NA, R+NA, NA);
+
+ unsigned i;
+
+ for (i=2*NA; i<NB; i+=2*NA)
+ Multiply(T+NA+i, T, A, B+i, NA);
+ for (i=NA; i<NB; i+=2*NA)
+ Multiply(R+i, T, A, B+i, NA);
+
+ if (Add(R+NA, R+NA, T+2*NA, NB-NA))
+ Increment(R+NB, NA);
+}
+
+
+void PositiveMultiply(Integer& product, const Integer& a, const Integer& b)
+{
+ unsigned int aSize = RoundupSize(a.WordCount());
+ unsigned int bSize = RoundupSize(b.WordCount());
+
+ product.reg_.CleanNew(RoundupSize(aSize + bSize));
+ product.sign_ = Integer::POSITIVE;
+
+ WordBlock workspace(aSize + bSize);
+ AsymmetricMultiply(product.reg_.get_buffer(), workspace.get_buffer(),
+ a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), bSize);
+}
+
+void Multiply(Integer &product, const Integer &a, const Integer &b)
+{
+ PositiveMultiply(product, a, b);
+
+ if (a.NotNegative() != b.NotNegative())
+ product.Negate();
+}
+
+
+static inline unsigned int EvenWordCount(const word *X, unsigned int N)
+{
+ while (N && X[N-2]==0 && X[N-1]==0)
+ N-=2;
+ return N;
+}
+
+
+unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA,
+ const word *M, unsigned int N)
+{
+ assert(NA<=N && N && N%2==0);
+
+ word *b = T;
+ word *c = T+N;
+ word *f = T+2*N;
+ word *g = T+3*N;
+ unsigned int bcLen=2, fgLen=EvenWordCount(M, N);
+ unsigned int k=0, s=0;
+
+ SetWords(T, 0, 3*N);
+ b[0]=1;
+ CopyWords(f, A, NA);
+ CopyWords(g, M, N);
+
+ while (1)
+ {
+ word t=f[0];
+ while (!t)
+ {
+ if (EvenWordCount(f, fgLen)==0)
+ {
+ SetWords(R, 0, N);
+ return 0;
+ }
+
+ ShiftWordsRightByWords(f, fgLen, 1);
+ if (c[bcLen-1]) bcLen+=2;
+ assert(bcLen <= N);
+ ShiftWordsLeftByWords(c, bcLen, 1);
+ k+=WORD_BITS;
+ t=f[0];
+ }
+
+ unsigned int i=0;
+ while (t%2 == 0)
+ {
+ t>>=1;
+ i++;
+ }
+ k+=i;
+
+ if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2)
+ {
+ if (s%2==0)
+ CopyWords(R, b, N);
+ else
+ Subtract(R, M, b, N);
+ return k;
+ }
+
+ ShiftWordsRightByBits(f, fgLen, i);
+ t=ShiftWordsLeftByBits(c, bcLen, i);
+ if (t)
+ {
+ c[bcLen] = t;
+ bcLen+=2;
+ assert(bcLen <= N);
+ }
+
+ if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0)
+ fgLen-=2;
+
+ if (Compare(f, g, fgLen)==-1)
+ {
+ mySTL::swap(f, g);
+ mySTL::swap(b, c);
+ s++;
+ }
+
+ Subtract(f, f, g, fgLen);
+
+ if (Add(b, b, c, bcLen))
+ {
+ b[bcLen] = 1;
+ bcLen+=2;
+ assert(bcLen <= N);
+ }
+ }
+}
+
+// R[N] - result = A/(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void DivideByPower2Mod(word *R, const word *A, unsigned int k, const word *M,
+ unsigned int N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ {
+ if (R[0]%2==0)
+ ShiftWordsRightByBits(R, N, 1);
+ else
+ {
+ word carry = Add(R, R, M, N);
+ ShiftWordsRightByBits(R, N, 1);
+ R[N-1] += carry<<(WORD_BITS-1);
+ }
+ }
+}
+
+// R[N] - result = A*(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void MultiplyByPower2Mod(word *R, const word *A, unsigned int k, const word *M,
+ unsigned int N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0)
+ Subtract(R, R, M, N);
+}
+
+
+// ********** end of integer needs
+
+
+Integer::Integer()
+ : reg_(2), sign_(POSITIVE)
+{
+ reg_[0] = reg_[1] = 0;
+}
+
+
+Integer::Integer(const Integer& t)
+ : reg_(RoundupSize(t.WordCount())), sign_(t.sign_)
+{
+ CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size());
+}
+
+
+Integer::Integer(signed long value)
+ : reg_(2)
+{
+ if (value >= 0)
+ sign_ = POSITIVE;
+ else
+ {
+ sign_ = NEGATIVE;
+ value = -value;
+ }
+ reg_[0] = word(value);
+ reg_[1] = word(SafeRightShift<WORD_BITS, unsigned long>(value));
+}
+
+
+Integer::Integer(Sign s, word high, word low)
+ : reg_(2), sign_(s)
+{
+ reg_[0] = low;
+ reg_[1] = high;
+}
+
+
+Integer::Integer(word value, unsigned int length)
+ : reg_(RoundupSize(length)), sign_(POSITIVE)
+{
+ reg_[0] = value;
+ SetWords(reg_ + 1, 0, reg_.size() - 1);
+}
+
+
+Integer::Integer(const char *str)
+ : reg_(2), sign_(POSITIVE)
+{
+ *this = StringToInteger(str);
+}
+
+
+Integer::Integer(const wchar_t *str)
+ : reg_(2), sign_(POSITIVE)
+{
+ *this = StringToInteger(str);
+}
+
+
+Integer::Integer(const byte *encodedInteger, unsigned int byteCount,
+ Signedness s)
+{
+ Decode(encodedInteger, byteCount, s);
+}
+
+class BadBER {};
+
+// BER Decode Source
+Integer::Integer(Source& source)
+ : reg_(2), sign_(POSITIVE)
+{
+ Decode(source);
+}
+
+void Integer::Decode(Source& source)
+{
+ byte b = source.next();
+ if (b != INTEGER) {
+ source.SetError(INTEGER_E);
+ return;
+ }
+
+ word32 length = GetLength(source);
+
+ if ( (b = source.next()) == 0x00)
+ length--;
+ else
+ source.prev();
+
+ unsigned int words = (length + WORD_SIZE - 1) / WORD_SIZE;
+ words = RoundupSize(words);
+ if (words > reg_.size()) reg_.CleanNew(words);
+
+ for (int j = length; j > 0; j--) {
+ b = source.next();
+ reg_ [(j-1) / WORD_SIZE] |= (word)b << ((j-1) % WORD_SIZE) * 8;
+ }
+}
+
+
+void Integer::Decode(const byte* input, unsigned int inputLen, Signedness s)
+{
+ unsigned int idx(0);
+ byte b = input[idx++];
+ sign_ = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE;
+
+ while (inputLen>0 && (sign_==POSITIVE ? b==0 : b==0xff))
+ {
+ inputLen--;
+ b = input[idx++];
+ }
+
+ reg_.CleanNew(RoundupSize(BytesToWords(inputLen)));
+
+ --idx;
+ for (unsigned int i=inputLen; i > 0; i--)
+ {
+ b = input[idx++];
+ reg_[(i-1)/WORD_SIZE] |= (word)b << ((i-1)%WORD_SIZE)*8;
+ }
+
+ if (sign_ == NEGATIVE)
+ {
+ for (unsigned i=inputLen; i<reg_.size()*WORD_SIZE; i++)
+ reg_[i/WORD_SIZE] |= (word)0xff << (i%WORD_SIZE)*8;
+ TwosComplement(reg_.get_buffer(), reg_.size());
+ }
+}
+
+
+unsigned int Integer::Encode(byte* output, unsigned int outputLen,
+ Signedness signedness) const
+{
+ unsigned int idx(0);
+ if (signedness == UNSIGNED || NotNegative())
+ {
+ for (unsigned int i=outputLen; i > 0; i--)
+ output[idx++] = GetByte(i-1);
+ }
+ else
+ {
+ // take two's complement of *this
+ Integer temp = Integer::Power2(8*max(ByteCount(), outputLen)) + *this;
+ for (unsigned i=0; i<outputLen; i++)
+ output[idx++] = temp.GetByte(outputLen-i-1);
+ }
+ return outputLen;
+}
+
+
+const Integer Integer::zero(1,2);
+
+const Integer &Integer::Zero()
+{
+ return zero;
+}
+
+const Integer Integer::one(1,2);
+
+const Integer &Integer::One()
+{
+ return one;
+}
+
+const Integer Integer::two(1,2);
+
+const Integer &Integer::Two()
+{
+ return two;
+}
+
+
+Integer::Integer(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max)
+{
+ Randomize(rng, min, max);
+}
+
+
+void Integer::Randomize(RandomNumberGenerator& rng, unsigned int nbits)
+{
+ const unsigned int nbytes = nbits/8 + 1;
+ ByteBlock buf(nbytes);
+ rng.GenerateBlock(buf.get_buffer(), nbytes);
+ if (nbytes)
+ buf[0] = (byte)Crop(buf[0], nbits % 8);
+ Decode(buf.get_buffer(), nbytes, UNSIGNED);
+}
+
+void Integer::Randomize(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max)
+{
+ assert(min <= max);
+
+ Integer range = max - min;
+ const unsigned int nbits = range.BitCount();
+
+ do
+ {
+ Randomize(rng, nbits);
+ }
+ while (*this > range);
+
+ *this += min;
+}
+
+
+Integer Integer::Power2(unsigned int e)
+{
+ Integer r((word)0, BitsToWords(e + 1));
+ r.SetBit(e);
+ return r;
+}
+
+
+void Integer::SetBit(unsigned int n, bool value)
+{
+ if (value)
+ {
+ reg_.CleanGrow(RoundupSize(BitsToWords(n + 1)));
+ reg_[n / WORD_BITS] |= (word(1) << (n % WORD_BITS));
+ }
+ else
+ {
+ if (n / WORD_BITS < reg_.size())
+ reg_[n / WORD_BITS] &= ~(word(1) << (n % WORD_BITS));
+ }
+}
+
+
+void Integer::SetByte(unsigned int n, byte value)
+{
+ reg_.CleanGrow(RoundupSize(BytesToWords(n+1)));
+ reg_[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
+ reg_[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
+}
+
+
+void Integer::Negate()
+{
+ if (!!(*this)) // don't flip sign if *this==0
+ sign_ = Sign(1 - sign_);
+}
+
+
+bool Integer::operator!() const
+{
+ return IsNegative() ? false : (reg_[0]==0 && WordCount()==0);
+}
+
+
+Integer& Integer::operator=(const Integer& t)
+{
+ if (this != &t)
+ {
+ reg_.New(RoundupSize(t.WordCount()));
+ CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size());
+ sign_ = t.sign_;
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator+=(const Integer& t)
+{
+ reg_.CleanGrow(t.reg_.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveAdd(*this, *this, t);
+ else
+ PositiveSubtract(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, t, *this);
+ else
+ {
+ PositiveAdd(*this, *this, t);
+ sign_ = Integer::NEGATIVE;
+ }
+ }
+ return *this;
+}
+
+
+Integer Integer::operator-() const
+{
+ Integer result(*this);
+ result.Negate();
+ return result;
+}
+
+
+Integer& Integer::operator-=(const Integer& t)
+{
+ reg_.CleanGrow(t.reg_.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, *this, t);
+ else
+ PositiveAdd(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ {
+ PositiveAdd(*this, *this, t);
+ sign_ = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(*this, t, *this);
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator++()
+{
+ if (NotNegative())
+ {
+ if (Increment(reg_.get_buffer(), reg_.size()))
+ {
+ reg_.CleanGrow(2*reg_.size());
+ reg_[reg_.size()/2]=1;
+ }
+ }
+ else
+ {
+ word borrow = Decrement(reg_.get_buffer(), reg_.size());
+ assert(!borrow);
+ if (WordCount()==0)
+ *this = Zero();
+ }
+ return *this;
+}
+
+Integer& Integer::operator--()
+{
+ if (IsNegative())
+ {
+ if (Increment(reg_.get_buffer(), reg_.size()))
+ {
+ reg_.CleanGrow(2*reg_.size());
+ reg_[reg_.size()/2]=1;
+ }
+ }
+ else
+ {
+ if (Decrement(reg_.get_buffer(), reg_.size()))
+ *this = -One();
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator<<=(unsigned int n)
+{
+ const unsigned int wordCount = WordCount();
+ const unsigned int shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = n % WORD_BITS;
+
+ reg_.CleanGrow(RoundupSize(wordCount+BitsToWords(n)));
+ ShiftWordsLeftByWords(reg_.get_buffer(), wordCount + shiftWords,
+ shiftWords);
+ ShiftWordsLeftByBits(reg_+shiftWords, wordCount+BitsToWords(shiftBits),
+ shiftBits);
+ return *this;
+}
+
+Integer& Integer::operator>>=(unsigned int n)
+{
+ const unsigned int wordCount = WordCount();
+ const unsigned int shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = n % WORD_BITS;
+
+ ShiftWordsRightByWords(reg_.get_buffer(), wordCount, shiftWords);
+ if (wordCount > shiftWords)
+ ShiftWordsRightByBits(reg_.get_buffer(), wordCount-shiftWords,
+ shiftBits);
+ if (IsNegative() && WordCount()==0) // avoid -0
+ *this = Zero();
+ return *this;
+}
+
+
+void PositiveAdd(Integer& sum, const Integer& a, const Integer& b)
+{
+ word carry;
+ if (a.reg_.size() == b.reg_.size())
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size());
+ else if (a.reg_.size() > b.reg_.size())
+ {
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), b.reg_.size());
+ CopyWords(sum.reg_+b.reg_.size(), a.reg_+b.reg_.size(),
+ a.reg_.size()-b.reg_.size());
+ carry = Increment(sum.reg_+b.reg_.size(), a.reg_.size()-b.reg_.size(),
+ carry);
+ }
+ else
+ {
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size());
+ CopyWords(sum.reg_+a.reg_.size(), b.reg_+a.reg_.size(),
+ b.reg_.size()-a.reg_.size());
+ carry = Increment(sum.reg_+a.reg_.size(), b.reg_.size()-a.reg_.size(),
+ carry);
+ }
+
+ if (carry)
+ {
+ sum.reg_.CleanGrow(2*sum.reg_.size());
+ sum.reg_[sum.reg_.size()/2] = 1;
+ }
+ sum.sign_ = Integer::POSITIVE;
+}
+
+void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ aSize += aSize%2;
+ unsigned bSize = b.WordCount();
+ bSize += bSize%2;
+
+ if (aSize == bSize)
+ {
+ if (Compare(a.reg_.get_buffer(), b.reg_.get_buffer(), aSize) >= 0)
+ {
+ Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), aSize);
+ diff.sign_ = Integer::POSITIVE;
+ }
+ else
+ {
+ Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(),
+ a.reg_.get_buffer(), aSize);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+ }
+ else if (aSize > bSize)
+ {
+ word borrow = Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), bSize);
+ CopyWords(diff.reg_+bSize, a.reg_+bSize, aSize-bSize);
+ borrow = Decrement(diff.reg_+bSize, aSize-bSize, borrow);
+ assert(!borrow);
+ diff.sign_ = Integer::POSITIVE;
+ }
+ else
+ {
+ word borrow = Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(),
+ a.reg_.get_buffer(), aSize);
+ CopyWords(diff.reg_+aSize, b.reg_+aSize, bSize-aSize);
+ borrow = Decrement(diff.reg_+aSize, bSize-aSize, borrow);
+ assert(!borrow);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+}
+
+
+unsigned int Integer::MinEncodedSize(Signedness signedness) const
+{
+ unsigned int outputLen = max(1U, ByteCount());
+ if (signedness == UNSIGNED)
+ return outputLen;
+ if (NotNegative() && (GetByte(outputLen-1) & 0x80))
+ outputLen++;
+ if (IsNegative() && *this < -Power2(outputLen*8-1))
+ outputLen++;
+ return outputLen;
+}
+
+
+int Integer::Compare(const Integer& t) const
+{
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ return PositiveCompare(t);
+ else
+ return 1;
+ }
+ else
+ {
+ if (t.NotNegative())
+ return -1;
+ else
+ return -PositiveCompare(t);
+ }
+}
+
+
+int Integer::PositiveCompare(const Integer& t) const
+{
+ unsigned size = WordCount(), tSize = t.WordCount();
+
+ if (size == tSize)
+ return TaoCrypt::Compare(reg_.get_buffer(), t.reg_.get_buffer(), size);
+ else
+ return size > tSize ? 1 : -1;
+}
+
+
+bool Integer::GetBit(unsigned int n) const
+{
+ if (n/WORD_BITS >= reg_.size())
+ return 0;
+ else
+ return bool((reg_[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
+}
+
+
+unsigned long Integer::GetBits(unsigned int i, unsigned int n) const
+{
+ assert(n <= sizeof(unsigned long)*8);
+ unsigned long v = 0;
+ for (unsigned int j=0; j<n; j++)
+ v |= GetBit(i+j) << j;
+ return v;
+}
+
+
+byte Integer::GetByte(unsigned int n) const
+{
+ if (n/WORD_SIZE >= reg_.size())
+ return 0;
+ else
+ return byte(reg_[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
+}
+
+
+unsigned int Integer::BitCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_BITS + BitPrecision(reg_[wordCount-1]);
+ else
+ return 0;
+}
+
+
+unsigned int Integer::ByteCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_SIZE + BytePrecision(reg_[wordCount-1]);
+ else
+ return 0;
+}
+
+
+unsigned int Integer::WordCount() const
+{
+ return CountWords(reg_.get_buffer(), reg_.size());
+}
+
+
+bool Integer::IsConvertableToLong() const
+{
+ if (ByteCount() > sizeof(long))
+ return false;
+
+ unsigned long value = reg_[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]);
+
+ if (sign_ == POSITIVE)
+ return (signed long)value >= 0;
+ else
+ return -(signed long)value < 0;
+}
+
+
+signed long Integer::ConvertToLong() const
+{
+ assert(IsConvertableToLong());
+
+ unsigned long value = reg_[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]);
+ return sign_ == POSITIVE ? value : -(signed long)value;
+}
+
+
+void Integer::Swap(Integer& a)
+{
+ reg_.Swap(a.reg_);
+ mySTL::swap(sign_, a.sign_);
+}
+
+
+Integer Integer::Plus(const Integer& b) const
+{
+ Integer sum((word)0, max(reg_.size(), b.reg_.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveAdd(sum, *this, b);
+ else
+ PositiveSubtract(sum, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ PositiveSubtract(sum, b, *this);
+ else
+ {
+ PositiveAdd(sum, *this, b);
+ sum.sign_ = Integer::NEGATIVE;
+ }
+ }
+ return sum;
+}
+
+
+Integer Integer::Minus(const Integer& b) const
+{
+ Integer diff((word)0, max(reg_.size(), b.reg_.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveSubtract(diff, *this, b);
+ else
+ PositiveAdd(diff, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ {
+ PositiveAdd(diff, *this, b);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(diff, b, *this);
+ }
+ return diff;
+}
+
+
+Integer Integer::Times(const Integer &b) const
+{
+ Integer product;
+ Multiply(product, *this, b);
+ return product;
+}
+
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+/*
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+static word SubatomicDivide(word *A, word B0, word B1)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ dword p, u;
+ word Q;
+
+ // estimate the quotient: do a 2 word by 1 word divide
+ if (B1+1 == 0)
+ Q = A[2];
+ else
+ Q = word(MAKE_DWORD(A[1], A[2]) / (B1+1));
+
+ // now subtract Q*B from A
+ p = (dword) B0*Q;
+ u = (dword) A[0] - LOW_WORD(p);
+ A[0] = LOW_WORD(u);
+ u = (dword) A[1] - HIGH_WORD(p) - (word)(0-HIGH_WORD(u)) - (dword)B1*Q;
+ A[1] = LOW_WORD(u);
+ A[2] += HIGH_WORD(u);
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (dword) A[0] - B0;
+ A[0] = LOW_WORD(u);
+ u = (dword) A[1] - B1 - (word)(0-HIGH_WORD(u));
+ A[1] = LOW_WORD(u);
+ A[2] += HIGH_WORD(u);
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+*/
+
+
+/*
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ if (!B[0] && !B[1]) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ {
+ Q[0] = A[2];
+ Q[1] = A[3];
+ }
+ else
+ {
+ word T[4];
+ T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3];
+ Q[1] = SubatomicDivide(T+1, B[0], B[1]);
+ Q[0] = SubatomicDivide(T, B[0], B[1]);
+
+#ifndef NDEBUG
+ // multiply quotient and divisor and add remainder
+ // make sure it equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ LowLevel::Multiply2(P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+#endif
+ }
+}
+*/
+
+
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ word T[4];
+ DWord q = DivideFourWordsByTwo<word, DWord>(T, DWord(A[0], A[1]),
+ DWord(A[2], A[3]), DWord(B[0], B[1]));
+ Q[0] = q.GetLowHalf();
+ Q[1] = q.GetHighHalf();
+
+#ifndef NDEBUG
+ if (B[0] || B[1])
+ {
+ // multiply quotient and divisor and add remainder, make sure it
+ // equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ Portable::Multiply2(P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+ }
+#endif
+}
+
+
+// for use by Divide(), corrects the underestimated quotient {Q1,Q0}
+static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B,
+ unsigned int N)
+{
+ assert(N && N%2==0);
+
+ if (Q[1])
+ {
+ T[N] = T[N+1] = 0;
+ unsigned i;
+ for (i=0; i<N; i+=4)
+ LowLevel::Multiply2(T+i, Q, B+i);
+ for (i=2; i<N; i+=4)
+ if (LowLevel::Multiply2Add(T+i, Q, B+i))
+ T[i+5] += (++T[i+4]==0);
+ }
+ else
+ {
+ T[N] = LinearMultiply(T, B, Q[0], N);
+ T[N+1] = 0;
+ }
+
+ word borrow = Subtract(R, R, T, N+2);
+ assert(!borrow && !R[N+1]);
+
+ while (R[N] || Compare(R, B, N) >= 0)
+ {
+ R[N] -= Subtract(R, R, B, N);
+ Q[1] += (++Q[0]==0);
+ assert(Q[0] || Q[1]); // no overflow
+ }
+}
+
+// R[NB] -------- remainder = A%B
+// Q[NA-NB+2] --- quotient = A/B
+// T[NA+2*NB+4] - temp work space
+// A[NA] -------- dividend
+// B[NB] -------- divisor
+
+
+void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA,
+ const word* B, unsigned int NB)
+{
+ assert(NA && NB && NA%2==0 && NB%2==0);
+ assert(B[NB-1] || B[NB-2]);
+ assert(NB <= NA);
+
+ // set up temporary work space
+ word *const TA=T;
+ word *const TB=T+NA+2;
+ word *const TP=T+NA+2+NB;
+
+ // copy B into TB and normalize it so that TB has highest bit set to 1
+ unsigned shiftWords = (B[NB-1]==0);
+ TB[0] = TB[NB-1] = 0;
+ CopyWords(TB+shiftWords, B, NB-shiftWords);
+ unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]);
+ assert(shiftBits < WORD_BITS);
+ ShiftWordsLeftByBits(TB, NB, shiftBits);
+
+ // copy A into TA and normalize it
+ TA[0] = TA[NA] = TA[NA+1] = 0;
+ CopyWords(TA+shiftWords, A, NA);
+ ShiftWordsLeftByBits(TA, NA+2, shiftBits);
+
+ if (TA[NA+1]==0 && TA[NA] <= 1)
+ {
+ Q[NA-NB+1] = Q[NA-NB] = 0;
+ while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0)
+ {
+ TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB);
+ ++Q[NA-NB];
+ }
+ }
+ else
+ {
+ NA+=2;
+ assert(Compare(TA+NA-NB, TB, NB) < 0);
+ }
+
+ word BT[2];
+ BT[0] = TB[NB-2] + 1;
+ BT[1] = TB[NB-1] + (BT[0]==0);
+
+ // start reducing TA mod TB, 2 words at a time
+ for (unsigned i=NA-2; i>=NB; i-=2)
+ {
+ AtomicDivide(Q+i-NB, TA+i-2, BT);
+ CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB);
+ }
+
+ // copy TA into R, and denormalize it
+ CopyWords(R, TA+shiftWords, NB);
+ ShiftWordsRightByBits(R, NB, shiftBits);
+}
+
+
+void PositiveDivide(Integer& remainder, Integer& quotient,
+ const Integer& a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ unsigned bSize = b.WordCount();
+
+ assert(bSize);
+
+ if (a.PositiveCompare(b) == -1)
+ {
+ remainder = a;
+ remainder.sign_ = Integer::POSITIVE;
+ quotient = Integer::Zero();
+ return;
+ }
+
+ aSize += aSize%2; // round up to next even number
+ bSize += bSize%2;
+
+ remainder.reg_.CleanNew(RoundupSize(bSize));
+ remainder.sign_ = Integer::POSITIVE;
+ quotient.reg_.CleanNew(RoundupSize(aSize-bSize+2));
+ quotient.sign_ = Integer::POSITIVE;
+
+ WordBlock T(aSize+2*bSize+4);
+ Divide(remainder.reg_.get_buffer(), quotient.reg_.get_buffer(),
+ T.get_buffer(), a.reg_.get_buffer(), aSize, b.reg_.get_buffer(),
+ bSize);
+}
+
+void Integer::Divide(Integer &remainder, Integer &quotient,
+ const Integer &dividend, const Integer &divisor)
+{
+ PositiveDivide(remainder, quotient, dividend, divisor);
+
+ if (dividend.IsNegative())
+ {
+ quotient.Negate();
+ if (remainder.NotZero())
+ {
+ --quotient;
+ remainder = divisor.AbsoluteValue() - remainder;
+ }
+ }
+
+ if (divisor.IsNegative())
+ quotient.Negate();
+}
+
+void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a,
+ unsigned int n)
+{
+ q = a;
+ q >>= n;
+
+ const unsigned int wordCount = BitsToWords(n);
+ if (wordCount <= a.WordCount())
+ {
+ r.reg_.resize(RoundupSize(wordCount));
+ CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), wordCount);
+ SetWords(r.reg_+wordCount, 0, r.reg_.size()-wordCount);
+ if (n % WORD_BITS != 0)
+ r.reg_[wordCount-1] %= (1 << (n % WORD_BITS));
+ }
+ else
+ {
+ r.reg_.resize(RoundupSize(a.WordCount()));
+ CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), r.reg_.size());
+ }
+ r.sign_ = POSITIVE;
+
+ if (a.IsNegative() && r.NotZero())
+ {
+ --q;
+ r = Power2(n) - r;
+ }
+}
+
+Integer Integer::DividedBy(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+Integer Integer::Modulo(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return remainder;
+}
+
+void Integer::Divide(word &remainder, Integer &quotient,
+ const Integer &dividend, word divisor)
+{
+ assert(divisor);
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ {
+ quotient = dividend >> (BitPrecision(divisor)-1);
+ remainder = dividend.reg_[0] & (divisor-1);
+ return;
+ }
+
+ unsigned int i = dividend.WordCount();
+ quotient.reg_.CleanNew(RoundupSize(i));
+ remainder = 0;
+ while (i--)
+ {
+ quotient.reg_[i] = DWord(dividend.reg_[i], remainder) / divisor;
+ remainder = DWord(dividend.reg_[i], remainder) % divisor;
+ }
+
+ if (dividend.NotNegative())
+ quotient.sign_ = POSITIVE;
+ else
+ {
+ quotient.sign_ = NEGATIVE;
+ if (remainder)
+ {
+ --quotient;
+ remainder = divisor - remainder;
+ }
+ }
+}
+
+Integer Integer::DividedBy(word b) const
+{
+ word remainder;
+ Integer quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+word Integer::Modulo(word divisor) const
+{
+ assert(divisor);
+
+ word remainder;
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ remainder = reg_[0] & (divisor-1);
+ else
+ {
+ unsigned int i = WordCount();
+
+ if (divisor <= 5)
+ {
+ DWord sum(0, 0);
+ while (i--)
+ sum += reg_[i];
+ remainder = sum % divisor;
+ }
+ else
+ {
+ remainder = 0;
+ while (i--)
+ remainder = DWord(reg_[i], remainder) % divisor;
+ }
+ }
+
+ if (IsNegative() && remainder)
+ remainder = divisor - remainder;
+
+ return remainder;
+}
+
+
+Integer Integer::AbsoluteValue() const
+{
+ Integer result(*this);
+ result.sign_ = POSITIVE;
+ return result;
+}
+
+
+Integer Integer::SquareRoot() const
+{
+ if (!IsPositive())
+ return Zero();
+
+ // overestimate square root
+ Integer x, y = Power2((BitCount()+1)/2);
+ assert(y*y >= *this);
+
+ do
+ {
+ x = y;
+ y = (x + *this/x) >> 1;
+ } while (y<x);
+
+ return x;
+}
+
+bool Integer::IsSquare() const
+{
+ Integer r = SquareRoot();
+ return *this == r.Squared();
+}
+
+bool Integer::IsUnit() const
+{
+ return (WordCount() == 1) && (reg_[0] == 1);
+}
+
+Integer Integer::MultiplicativeInverse() const
+{
+ return IsUnit() ? *this : Zero();
+}
+
+Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m)
+{
+ return x*y%m;
+}
+
+Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m)
+{
+ ModularArithmetic mr(m);
+ return mr.Exponentiate(x, e);
+}
+
+Integer Integer::Gcd(const Integer &a, const Integer &b)
+{
+ return EuclideanDomainOf<Integer>().Gcd(a, b);
+}
+
+Integer Integer::InverseMod(const Integer &m) const
+{
+ assert(m.NotNegative());
+
+ if (IsNegative() || *this>=m)
+ return (*this%m).InverseMod(m);
+
+ if (m.IsEven())
+ {
+ if (!m || IsEven())
+ return Zero(); // no inverse
+ if (*this == One())
+ return One();
+
+ Integer u = m.InverseMod(*this);
+ return !u ? Zero() : (m*(*this-u)+1)/(*this);
+ }
+
+ WordBlock T(m.reg_.size() * 4);
+ Integer r((word)0, m.reg_.size());
+ unsigned k = AlmostInverse(r.reg_.get_buffer(), T.get_buffer(),
+ reg_.get_buffer(), reg_.size(),
+ m.reg_.get_buffer(), m.reg_.size());
+ DivideByPower2Mod(r.reg_.get_buffer(), r.reg_.get_buffer(), k,
+ m.reg_.get_buffer(), m.reg_.size());
+ return r;
+}
+
+word Integer::InverseMod(const word mod) const
+{
+ word g0 = mod, g1 = *this % mod;
+ word v0 = 0, v1 = 1;
+ word y;
+
+ while (g1)
+ {
+ if (g1 == 1)
+ return v1;
+ y = g0 / g1;
+ g0 = g0 % g1;
+ v0 += y * v1;
+
+ if (!g0)
+ break;
+ if (g0 == 1)
+ return mod-v0;
+ y = g1 / g0;
+ g1 = g1 % g0;
+ v1 += y * v0;
+ }
+ return 0;
+}
+
+// ********* ModArith stuff
+
+const Integer& ModularArithmetic::Half(const Integer &a) const
+{
+ if (a.reg_.size()==modulus.reg_.size())
+ {
+ TaoCrypt::DivideByPower2Mod(result.reg_.begin(), a.reg_.begin(), 1,
+ modulus.reg_.begin(), a.reg_.size());
+ return result;
+ }
+ else
+ return result1 = (a.IsEven() ? (a >> 1) : ((a+modulus) >> 1));
+}
+
+const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Add(result.reg_.begin(), a.reg_.begin(), b.reg_.begin(),
+ a.reg_.size())
+ || Compare(result.reg_.get_buffer(), modulus.reg_.get_buffer(),
+ a.reg_.size()) >= 0)
+ {
+ TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(),
+ modulus.reg_.begin(), a.reg_.size());
+ }
+ return result;
+ }
+ else
+ {
+ result1 = a+b;
+ if (result1 >= modulus)
+ result1 -= modulus;
+ return result1;
+ }
+}
+
+Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size())
+ || Compare(a.reg_.get_buffer(), modulus.reg_.get_buffer(),
+ a.reg_.size()) >= 0)
+ {
+ TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ modulus.reg_.get_buffer(), a.reg_.size());
+ }
+ }
+ else
+ {
+ a+=b;
+ if (a>=modulus)
+ a-=modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Subtract(const Integer &a,
+ const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Subtract(result.reg_.begin(), a.reg_.begin(),
+ b.reg_.begin(), a.reg_.size()))
+ TaoCrypt::Add(result.reg_.begin(), result.reg_.begin(),
+ modulus.reg_.begin(), a.reg_.size());
+ return result;
+ }
+ else
+ {
+ result1 = a-b;
+ if (result1.IsNegative())
+ result1 += modulus;
+ return result1;
+ }
+}
+
+Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size()))
+ TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ modulus.reg_.get_buffer(), a.reg_.size());
+ }
+ else
+ {
+ a-=b;
+ if (a.IsNegative())
+ a+=modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Inverse(const Integer &a) const
+{
+ if (!a)
+ return a;
+
+ CopyWords(result.reg_.begin(), modulus.reg_.begin(), modulus.reg_.size());
+ if (TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(),
+ a.reg_.begin(), a.reg_.size()))
+ Decrement(result.reg_.begin()+a.reg_.size(), 1,
+ modulus.reg_.size()-a.reg_.size());
+
+ return result;
+}
+
+Integer ModularArithmetic::CascadeExponentiate(const Integer &x,
+ const Integer &e1, const Integer &y, const Integer &e2) const
+{
+ if (modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(modulus);
+ return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1,
+ dr.ConvertIn(y), e2));
+ }
+ else
+ return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);
+}
+
+void ModularArithmetic::SimultaneousExponentiate(Integer *results,
+ const Integer &base, const Integer *exponents,
+ unsigned int exponentsCount) const
+{
+ if (modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(modulus);
+ dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents,
+ exponentsCount);
+ for (unsigned int i=0; i<exponentsCount; i++)
+ results[i] = dr.ConvertOut(results[i]);
+ }
+ else
+ AbstractRing<Integer>::SimultaneousExponentiate(results, base,
+ exponents, exponentsCount);
+}
+
+
+// ********************************************************
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+
+inline void MultiplyBottom(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ RecursiveMultiplyBottom(R, T, A, B, N);
+}
+
+inline void MultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N)
+{
+ RecursiveMultiplyTop(R, T, L, A, B, N);
+}
+
+
+// R[N] --- result = X/(2**(WORD_BITS*N)) mod M
+// T[3*N] - temporary work space
+// X[2*N] - number to be reduced
+// M[N] --- modulus
+// U[N] --- multiplicative inverse of M mod 2**(WORD_BITS*N)
+
+void MontgomeryReduce(word *R, word *T, const word *X, const word *M,
+ const word *U, unsigned int N)
+{
+ MultiplyBottom(R, T, X, U, N);
+ MultiplyTop(T, T+N, X, R, M, N);
+ word borrow = Subtract(T, X+N, T, N);
+ // defend against timing attack by doing this Add even when not needed
+ word carry = Add(T+N, T, M, N);
+ assert(carry || !borrow);
+ CopyWords(R, T + (borrow ? N : 0), N);
+}
+
+// R[N] ----- result = A inverse mod 2**(WORD_BITS*N)
+// T[3*N/2] - temporary work space
+// A[N] ----- an odd number as input
+
+void RecursiveInverseModPower2(word *R, word *T, const word *A, unsigned int N)
+{
+ if (N==2)
+ {
+ T[0] = AtomicInverseModPower2(A[0]);
+ T[1] = 0;
+ LowLevel::Multiply2Bottom(T+2, T, A);
+ TwosComplement(T+2, 2);
+ Increment(T+2, 2, 2);
+ LowLevel::Multiply2Bottom(R, T, T+2);
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ RecursiveInverseModPower2(R0, T0, A0, N2);
+ T0[0] = 1;
+ SetWords(T0+1, 0, N2-1);
+ MultiplyTop(R1, T1, T0, R0, A0, N2);
+ MultiplyBottom(T0, T1, R0, A1, N2);
+ Add(T0, R1, T0, N2);
+ TwosComplement(T0, N2);
+ MultiplyBottom(R1, T1, R0, T0, N2);
+ }
+}
+
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+
+// modulus must be odd
+MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m)
+ : ModularArithmetic(m),
+ u((word)0, modulus.reg_.size()),
+ workspace(5*modulus.reg_.size())
+{
+ assert(modulus.IsOdd());
+ RecursiveInverseModPower2(u.reg_.get_buffer(), workspace.get_buffer(),
+ modulus.reg_.get_buffer(), modulus.reg_.size());
+}
+
+const Integer& MontgomeryRepresentation::Multiply(const Integer &a,
+ const Integer &b) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N && b.reg_.size()<=N);
+
+ AsymmetricMultiply(T, T+2*N, a.reg_.get_buffer(), a.reg_.size(),
+ b.reg_.get_buffer(), b.reg_.size());
+ SetWords(T+a.reg_.size()+b.reg_.size(),0, 2*N-a.reg_.size()-b.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+const Integer& MontgomeryRepresentation::Square(const Integer &a) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ TaoCrypt::Square(T, T+2*N, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+2*a.reg_.size(), 0, 2*N-2*a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ CopyWords(T, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+const Integer& MontgomeryRepresentation::MultiplicativeInverse(
+ const Integer &a) const
+{
+// return (EuclideanMultiplicativeInverse(a, modulus)<<
+// (2*WORD_BITS*modulus.reg_.size()))%modulus;
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ CopyWords(T, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ unsigned k = AlmostInverse(R, T, R, N, modulus.reg_.get_buffer(), N);
+
+// cout << "k=" << k << " N*32=" << 32*N << endl;
+
+ if (k>N*WORD_BITS)
+ DivideByPower2Mod(R, R, k-N*WORD_BITS, modulus.reg_.get_buffer(), N);
+ else
+ MultiplyByPower2Mod(R, R, N*WORD_BITS-k, modulus.reg_.get_buffer(), N);
+
+ return result;
+}
+
+
+// mod Root stuff
+Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
+ const Integer &p, const Integer &q, const Integer &u)
+{
+ Integer p2 = ModularExponentiation((a % p), dp, p);
+ Integer q2 = ModularExponentiation((a % q), dq, q);
+ return CRT(p2, p, q2, q, u);
+}
+
+Integer CRT(const Integer &xp, const Integer &p, const Integer &xq,
+ const Integer &q, const Integer &u)
+{
+ // isn't operator overloading great?
+ return p * (u * (xq-xp) % q) + xp;
+}
+
+#ifdef __GNUC__
+template Integer StringToInteger<char>(char const*);
+template Integer StringToInteger<wchar_t>(wchar_t const*);
+template class EuclideanDomainOf<Integer>;
+template class AbstractEuclideanDomain<Integer>;
+template unsigned int DivideThreeWordsByTwo<unsigned int, DWord>(unsigned int*, unsigned int, unsigned int, DWord*);
+#endif
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/md2.cpp b/extra/yassl/taocrypt/src/md2.cpp
new file mode 100644
index 00000000000..16834b6bc89
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md2.cpp
@@ -0,0 +1,128 @@
+/* md2.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's md2.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md2.hpp"
+#include <string.h>
+
+namespace TaoCrypt {
+
+
+MD2::MD2()
+ : X_(X_SIZE), C_(BLOCK_SIZE), buffer_(BLOCK_SIZE)
+{
+ Init();
+}
+
+void MD2::Init()
+{
+ memset(X_.get_buffer(), 0, X_SIZE);
+ memset(C_.get_buffer(), 0, BLOCK_SIZE);
+ memset(buffer_.get_buffer(), 0, BLOCK_SIZE);
+ count_ = 0;
+}
+
+
+void MD2::Update(const byte* data, word32 len)
+{
+
+ static const byte S[256] =
+ {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+ };
+
+ while (len) {
+ word32 L = (PAD_SIZE - count_) < len ? (PAD_SIZE - count_) : len;
+ memcpy(buffer_.get_buffer() + count_, data, L);
+ count_ += L;
+ data += L;
+ len -= L;
+
+ if (count_==PAD_SIZE) {
+ count_ = 0;
+ memcpy(X_.get_buffer() + PAD_SIZE, buffer_.get_buffer(), PAD_SIZE);
+ byte t = C_[15];
+
+ int i;
+ for(i = 0; i < PAD_SIZE; i++) {
+ X_[32 + i] = X_[PAD_SIZE + i] ^ X_[i];
+ t = C_[i] ^= S[buffer_[i] ^ t];
+ }
+
+ t=0;
+ for(i = 0; i < 18; i++) {
+ for(int j = 0; j < X_SIZE; j += 8) {
+ t = X_[j+0] ^= S[t];
+ t = X_[j+1] ^= S[t];
+ t = X_[j+2] ^= S[t];
+ t = X_[j+3] ^= S[t];
+ t = X_[j+4] ^= S[t];
+ t = X_[j+5] ^= S[t];
+ t = X_[j+6] ^= S[t];
+ t = X_[j+7] ^= S[t];
+ }
+ t = (t + i) & 0xFF;
+ }
+ }
+ }
+}
+
+
+void MD2::Final(byte *hash)
+{
+ byte padding[BLOCK_SIZE];
+ word32 padLen = PAD_SIZE - count_;
+
+ for (word32 i = 0; i < padLen; i++)
+ padding[i] = static_cast<byte>(padLen);
+
+ Update(padding, padLen);
+ Update(C_.get_buffer(), BLOCK_SIZE);
+
+ memcpy(hash, X_.get_buffer(), DIGEST_SIZE);
+
+ Init();
+}
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp
new file mode 100644
index 00000000000..b9777e93216
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md5.cpp
@@ -0,0 +1,169 @@
+/* md5.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's md5.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md5.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+namespace TaoCrypt {
+
+void MD5::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+MD5::MD5(const MD5& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+MD5& MD5::operator= (const MD5& that)
+{
+ MD5 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void MD5::Swap(MD5& other)
+{
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(buffLen_, other.buffLen_);
+ mySTL::swap(digest_, other.digest_);
+ mySTL::swap(length_, other.length_);
+}
+
+
+void MD5::Transform()
+{
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ w = rotlFixed(w + f(x, y, z) + data, s) + x
+
+ // Copy context->state[] to working vars
+ word32 a = digest_[0];
+ word32 b = digest_[1];
+ word32 c = digest_[2];
+ word32 d = digest_[3];
+
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[0*4] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[1*4] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[2*4] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[3*4] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[4*4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[5*4] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[6*4] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[7*4] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[8*4] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[9*4] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[10*4] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[11*4] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[12*4] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[13*4] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[14*4] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[15*4] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[1*4] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[6*4] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[11*4] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[0*4] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[5*4] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[10*4] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[15*4] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[4*4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[9*4] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[14*4] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[3*4] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[8*4] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[13*4] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[2*4] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[7*4] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[12*4] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[5*4] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[8*4] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[11*4] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[14*4] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[1*4] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[4*4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[7*4] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[10*4] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[13*4] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[0*4] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[3*4] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[6*4] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[9*4] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[12*4] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[15*4] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[2*4] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[0*4] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[7*4] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[14*4] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[5*4] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[12*4] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[3*4] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[10*4] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[1*4] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[8*4] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[15*4] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[6*4] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[13*4] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[4*4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[11*4] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[2*4] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[9*4] + 0xeb86d391, 21);
+
+ // Add the working vars back into digest state[]
+ digest_[0] += a;
+ digest_[1] += b;
+ digest_[2] += c;
+ digest_[3] += d;
+
+ // Wipe variables
+ a = b = c = d = 0;
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp
new file mode 100644
index 00000000000..e4573abac3f
--- /dev/null
+++ b/extra/yassl/taocrypt/src/misc.cpp
@@ -0,0 +1,132 @@
+/* misc.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's misc.cpp from CryptoPP */
+
+
+#include "runtime.hpp"
+#include "misc.hpp"
+#include <new> // for NewHandler
+
+
+void* operator new(size_t sz, TaoCrypt::new_t)
+{
+ void* ptr = ::operator new(sz);
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+void* operator new[](size_t sz, TaoCrypt::new_t tc)
+{
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ void* ptr = ::operator new(sz); // no ::operator new[]
+#else
+ void* ptr = ::operator new[](sz);
+#endif
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+
+
+namespace TaoCrypt {
+
+
+new_t tc; // for library new
+
+
+inline void XorWords(word* r, const word* a, unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ r[i] ^= a[i];
+}
+
+
+void xorbuf(byte* buf, const byte* mask, unsigned int count)
+{
+ if (((size_t)buf | (size_t)mask | count) % WORD_SIZE == 0)
+ XorWords((word *)buf, (const word *)mask, count/WORD_SIZE);
+ else
+ {
+ for (unsigned int i=0; i<count; i++)
+ buf[i] ^= mask[i];
+ }
+}
+
+
+unsigned int BytePrecision(unsigned long value)
+{
+ unsigned int i;
+ for (i=sizeof(value); i; --i)
+ if (value >> (i-1)*8)
+ break;
+
+ return i;
+}
+
+
+unsigned int BitPrecision(unsigned long value)
+{
+ if (!value)
+ return 0;
+
+ unsigned int l = 0,
+ h = 8 * sizeof(value);
+
+ while (h-l > 1)
+ {
+ unsigned int t = (l+h)/2;
+ if (value >> t)
+ l = t;
+ else
+ h = t;
+ }
+
+ return h;
+}
+
+
+unsigned long Crop(unsigned long value, unsigned int size)
+{
+ if (size < 8*sizeof(value))
+ return (value & ((1L << size) - 1));
+ else
+ return value;
+}
+
+
+#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
+using std::new_handler;
+using std::set_new_handler;
+#endif
+
+void CallNewHandler()
+{
+ abort();
+}
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp
new file mode 100644
index 00000000000..5c9e3b0f02a
--- /dev/null
+++ b/extra/yassl/taocrypt/src/random.cpp
@@ -0,0 +1,131 @@
+/* random.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* random.cpp implements a crypto secure Random Number Generator using an OS
+ specific seed, switch to /dev/random for more security but may block
+*/
+
+#include "runtime.hpp"
+#include "random.hpp"
+#include "stdexcept.hpp"
+
+#if defined(WIN32)
+ #define _WIN32_WINNT 0x0400
+ #include <windows.h>
+ #include <wincrypt.h>
+#else
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+#endif // WIN32
+
+namespace TaoCrypt {
+
+
+// Get seed and key cipher
+RandomNumberGenerator::RandomNumberGenerator()
+{
+ byte key[32];
+ seed_.GenerateSeed(key, sizeof(key));
+ cipher_.SetKey(key, sizeof(key));
+}
+
+
+// place a generated block in output
+void RandomNumberGenerator::GenerateBlock(byte* output, word32 sz)
+{
+ cipher_.Process(output, output, sz);
+}
+
+
+byte RandomNumberGenerator::GenerateByte()
+{
+ byte b;
+ GenerateBlock(&b, 1);
+
+ return b;
+}
+
+
+#if defined(WIN32)
+
+OS_Seed::OS_Seed()
+{
+ if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ error_.SetError(WINCRYPT_E);
+}
+
+
+OS_Seed::~OS_Seed()
+{
+ CryptReleaseContext(handle_, 0);
+}
+
+
+void OS_Seed::GenerateSeed(byte* output, word32 sz)
+{
+ if (!CryptGenRandom(handle_, sz, output))
+ error_.SetError(CRYPTGEN_E);
+}
+
+
+#else // WIN32
+
+
+OS_Seed::OS_Seed()
+{
+ fd_ = open("/dev/urandom",O_RDONLY);
+ if (fd_ == -1)
+ error_.SetError(OPEN_RAN_E);
+}
+
+
+OS_Seed::~OS_Seed()
+{
+ close(fd_);
+}
+
+
+// may block
+void OS_Seed::GenerateSeed(byte* output, word32 sz)
+{
+ while (sz) {
+ int len = read(fd_, output, sz);
+ if (len == -1) {
+ error_.SetError(READ_RAN_E);
+ return;
+ }
+
+ sz -= len;
+ output += len;
+
+ if (sz)
+ sleep(1);
+ }
+}
+
+#endif // WIN32
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp
new file mode 100644
index 00000000000..53f573cac32
--- /dev/null
+++ b/extra/yassl/taocrypt/src/ripemd.cpp
@@ -0,0 +1,289 @@
+/* ripemd.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's ripemd.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "ripemd.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+namespace TaoCrypt {
+
+void RIPEMD160::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+ digest_[4] = 0xc3d2e1f0L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+RIPEMD160::RIPEMD160(const RIPEMD160& that)
+ : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+
+RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that)
+{
+ RIPEMD160 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void RIPEMD160::Swap(RIPEMD160& other)
+{
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(buffLen_, other.buffLen_);
+ mySTL::swap(digest_, other.digest_);
+ mySTL::swap(length_, other.length_);
+}
+
+
+// for all
+#define F(x, y, z) (x ^ y ^ z)
+#define G(x, y, z) (z ^ (x & (y^z)))
+#define H(x, y, z) (z ^ (x | ~y))
+#define I(x, y, z) (y ^ (z & (x^y)))
+#define J(x, y, z) (x ^ (y | ~z))
+
+#define k0 0
+#define k1 0x5a827999UL
+#define k2 0x6ed9eba1UL
+#define k3 0x8f1bbcdcUL
+#define k4 0xa953fd4eUL
+#define k5 0x50a28be6UL
+#define k6 0x5c4dd124UL
+#define k7 0x6d703ef3UL
+#define k8 0x7a6d76e9UL
+#define k9 0
+
+// for 160 and 320
+#define Subround(f, a, b, c, d, e, x, s, k) \
+ a += f(b, c, d) + x + k;\
+ a = rotlFixed((word32)a, s) + e;\
+ c = rotlFixed((word32)c, 10U)
+
+
+void RIPEMD160::Transform()
+{
+ unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2;
+ a1 = a2 = digest_[0];
+ b1 = b2 = digest_[1];
+ c1 = c2 = digest_[2];
+ d1 = d2 = digest_[3];
+ e1 = e2 = digest_[4];
+
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 0*4], 11, k0);
+ Subround(F, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 1*4], 14, k0);
+ Subround(F, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 2*4], 15, k0);
+ Subround(F, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 3*4], 12, k0);
+ Subround(F, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 4*4], 5, k0);
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 5*4], 8, k0);
+ Subround(F, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 6*4], 7, k0);
+ Subround(F, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 7*4], 9, k0);
+ Subround(F, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 8*4], 11, k0);
+ Subround(F, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 9*4], 13, k0);
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[10*4], 14, k0);
+ Subround(F, e1, a1, b1, c1, d1, *(word32*)&buffer_[11*4], 15, k0);
+ Subround(F, d1, e1, a1, b1, c1, *(word32*)&buffer_[12*4], 6, k0);
+ Subround(F, c1, d1, e1, a1, b1, *(word32*)&buffer_[13*4], 7, k0);
+ Subround(F, b1, c1, d1, e1, a1, *(word32*)&buffer_[14*4], 9, k0);
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[15*4], 8, k0);
+
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 7*4], 7, k1);
+ Subround(G, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 4*4], 6, k1);
+ Subround(G, c1, d1, e1, a1, b1, *(word32*)&buffer_[13*4], 8, k1);
+ Subround(G, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 1*4], 13, k1);
+ Subround(G, a1, b1, c1, d1, e1, *(word32*)&buffer_[10*4], 11, k1);
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 6*4], 9, k1);
+ Subround(G, d1, e1, a1, b1, c1, *(word32*)&buffer_[15*4], 7, k1);
+ Subround(G, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 3*4], 15, k1);
+ Subround(G, b1, c1, d1, e1, a1, *(word32*)&buffer_[12*4], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 0*4], 12, k1);
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 9*4], 15, k1);
+ Subround(G, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 5*4], 9, k1);
+ Subround(G, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 2*4], 11, k1);
+ Subround(G, b1, c1, d1, e1, a1, *(word32*)&buffer_[14*4], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, *(word32*)&buffer_[11*4], 13, k1);
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 8*4], 12, k1);
+
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 3*4], 11, k2);
+ Subround(H, c1, d1, e1, a1, b1, *(word32*)&buffer_[10*4], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, *(word32*)&buffer_[14*4], 6, k2);
+ Subround(H, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 4*4], 7, k2);
+ Subround(H, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 9*4], 14, k2);
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[15*4], 9, k2);
+ Subround(H, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 8*4], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 1*4], 15, k2);
+ Subround(H, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 2*4], 14, k2);
+ Subround(H, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 7*4], 8, k2);
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 0*4], 13, k2);
+ Subround(H, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 6*4], 6, k2);
+ Subround(H, b1, c1, d1, e1, a1, *(word32*)&buffer_[13*4], 5, k2);
+ Subround(H, a1, b1, c1, d1, e1, *(word32*)&buffer_[11*4], 12, k2);
+ Subround(H, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 5*4], 7, k2);
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[12*4], 5, k2);
+
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 1*4], 11, k3);
+ Subround(I, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 9*4], 12, k3);
+ Subround(I, a1, b1, c1, d1, e1, *(word32*)&buffer_[11*4], 14, k3);
+ Subround(I, e1, a1, b1, c1, d1, *(word32*)&buffer_[10*4], 15, k3);
+ Subround(I, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 0*4], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 8*4], 15, k3);
+ Subround(I, b1, c1, d1, e1, a1, *(word32*)&buffer_[12*4], 9, k3);
+ Subround(I, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 4*4], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, *(word32*)&buffer_[13*4], 9, k3);
+ Subround(I, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 3*4], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 7*4], 5, k3);
+ Subround(I, b1, c1, d1, e1, a1, *(word32*)&buffer_[15*4], 6, k3);
+ Subround(I, a1, b1, c1, d1, e1, *(word32*)&buffer_[14*4], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 5*4], 6, k3);
+ Subround(I, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 6*4], 5, k3);
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 2*4], 12, k3);
+
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 4*4], 9, k4);
+ Subround(J, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 0*4], 15, k4);
+ Subround(J, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 5*4], 5, k4);
+ Subround(J, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 9*4], 11, k4);
+ Subround(J, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 7*4], 6, k4);
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[12*4], 8, k4);
+ Subround(J, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 2*4], 13, k4);
+ Subround(J, e1, a1, b1, c1, d1, *(word32*)&buffer_[10*4], 12, k4);
+ Subround(J, d1, e1, a1, b1, c1, *(word32*)&buffer_[14*4], 5, k4);
+ Subround(J, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 1*4], 12, k4);
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 3*4], 13, k4);
+ Subround(J, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 8*4], 14, k4);
+ Subround(J, e1, a1, b1, c1, d1, *(word32*)&buffer_[11*4], 11, k4);
+ Subround(J, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 6*4], 8, k4);
+ Subround(J, c1, d1, e1, a1, b1, *(word32*)&buffer_[15*4], 5, k4);
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[13*4], 6, k4);
+
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 5*4], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, *(word32*)&buffer_[14*4], 9, k5);
+ Subround(J, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 7*4], 9, k5);
+ Subround(J, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 0*4], 11, k5);
+ Subround(J, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 9*4], 13, k5);
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 2*4], 15, k5);
+ Subround(J, e2, a2, b2, c2, d2, *(word32*)&buffer_[11*4], 15, k5);
+ Subround(J, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 4*4], 5, k5);
+ Subround(J, c2, d2, e2, a2, b2, *(word32*)&buffer_[13*4], 7, k5);
+ Subround(J, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 6*4], 7, k5);
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[15*4], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 8*4], 11, k5);
+ Subround(J, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 1*4], 14, k5);
+ Subround(J, c2, d2, e2, a2, b2, *(word32*)&buffer_[10*4], 14, k5);
+ Subround(J, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 3*4], 12, k5);
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[12*4], 6, k5);
+
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 6*4], 9, k6);
+ Subround(I, d2, e2, a2, b2, c2, *(word32*)&buffer_[11*4], 13, k6);
+ Subround(I, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 3*4], 15, k6);
+ Subround(I, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 7*4], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 0*4], 12, k6);
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[13*4], 8, k6);
+ Subround(I, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 5*4], 9, k6);
+ Subround(I, c2, d2, e2, a2, b2, *(word32*)&buffer_[10*4], 11, k6);
+ Subround(I, b2, c2, d2, e2, a2, *(word32*)&buffer_[14*4], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, *(word32*)&buffer_[15*4], 7, k6);
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 8*4], 12, k6);
+ Subround(I, d2, e2, a2, b2, c2, *(word32*)&buffer_[12*4], 7, k6);
+ Subround(I, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 4*4], 6, k6);
+ Subround(I, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 9*4], 15, k6);
+ Subround(I, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 1*4], 13, k6);
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 2*4], 11, k6);
+
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[15*4], 9, k7);
+ Subround(H, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 5*4], 7, k7);
+ Subround(H, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 1*4], 15, k7);
+ Subround(H, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 3*4], 11, k7);
+ Subround(H, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 7*4], 8, k7);
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[14*4], 6, k7);
+ Subround(H, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 6*4], 6, k7);
+ Subround(H, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 9*4], 14, k7);
+ Subround(H, a2, b2, c2, d2, e2, *(word32*)&buffer_[11*4], 12, k7);
+ Subround(H, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 8*4], 13, k7);
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[12*4], 5, k7);
+ Subround(H, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 2*4], 14, k7);
+ Subround(H, b2, c2, d2, e2, a2, *(word32*)&buffer_[10*4], 13, k7);
+ Subround(H, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 0*4], 13, k7);
+ Subround(H, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 4*4], 7, k7);
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[13*4], 5, k7);
+
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 8*4], 15, k8);
+ Subround(G, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 6*4], 5, k8);
+ Subround(G, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 4*4], 8, k8);
+ Subround(G, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 1*4], 11, k8);
+ Subround(G, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 3*4], 14, k8);
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[11*4], 14, k8);
+ Subround(G, b2, c2, d2, e2, a2, *(word32*)&buffer_[15*4], 6, k8);
+ Subround(G, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 0*4], 14, k8);
+ Subround(G, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 5*4], 6, k8);
+ Subround(G, d2, e2, a2, b2, c2, *(word32*)&buffer_[12*4], 9, k8);
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 2*4], 12, k8);
+ Subround(G, b2, c2, d2, e2, a2, *(word32*)&buffer_[13*4], 9, k8);
+ Subround(G, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 9*4], 12, k8);
+ Subround(G, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 7*4], 5, k8);
+ Subround(G, d2, e2, a2, b2, c2, *(word32*)&buffer_[10*4], 15, k8);
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[14*4], 8, k8);
+
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[12*4], 8, k9);
+ Subround(F, a2, b2, c2, d2, e2, *(word32*)&buffer_[15*4], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, *(word32*)&buffer_[10*4], 12, k9);
+ Subround(F, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 4*4], 9, k9);
+ Subround(F, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 1*4], 12, k9);
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 5*4], 5, k9);
+ Subround(F, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 8*4], 14, k9);
+ Subround(F, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 7*4], 6, k9);
+ Subround(F, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 6*4], 8, k9);
+ Subround(F, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 2*4], 13, k9);
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[13*4], 6, k9);
+ Subround(F, a2, b2, c2, d2, e2, *(word32*)&buffer_[14*4], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 0*4], 15, k9);
+ Subround(F, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 3*4], 13, k9);
+ Subround(F, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 9*4], 11, k9);
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[11*4], 11, k9);
+
+ c1 = digest_[1] + c1 + d2;
+ digest_[1] = digest_[2] + d1 + e2;
+ digest_[2] = digest_[3] + e1 + a2;
+ digest_[3] = digest_[4] + a1 + b2;
+ digest_[4] = digest_[0] + b1 + c2;
+ digest_[0] = c1;
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+
+} // namespace TaoCrypt
diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp
new file mode 100644
index 00000000000..ecb2288f1c2
--- /dev/null
+++ b/extra/yassl/taocrypt/src/rsa.cpp
@@ -0,0 +1,238 @@
+/* rsa.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's rsa.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "rsa.hpp"
+#include "asn.hpp"
+#include "modarith.hpp"
+#include "stdexcept.hpp"
+
+#include "algebra.cpp" // for GCC 3.2 on aix ?
+
+
+namespace TaoCrypt {
+
+
+Integer RSA_PublicKey::ApplyFunction(const Integer& x) const
+{
+ return a_exp_b_mod_c(x, e_, n_);
+}
+
+
+RSA_PublicKey::RSA_PublicKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void RSA_PublicKey::Initialize(Source& source)
+{
+ RSA_Public_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+Integer RSA_PrivateKey::CalculateInverse(RandomNumberGenerator& rng,
+ const Integer& x) const
+{
+ ModularArithmetic modn(n_);
+
+ Integer r(rng, Integer::One(), n_ - Integer::One());
+ Integer re = modn.Exponentiate(r, e_);
+ re = modn.Multiply(re, x); // blind
+
+ // here we follow the notation of PKCS #1 and let u=q inverse mod p
+ // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
+
+ Integer y = ModularRoot(re, dq_, dp_, q_, p_, u_);
+ y = modn.Divide(y, r); // unblind
+ assert(modn.Exponentiate(y, e_) == x); // check
+
+ return y;
+}
+
+
+RSA_PrivateKey::RSA_PrivateKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void RSA_PrivateKey::Initialize(Source& source)
+{
+ RSA_Private_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void RSA_BlockType2::Pad(const byte *input, word32 inputLen, byte *pkcsBlock,
+ word32 pkcsBlockLen, RandomNumberGenerator& rng) const
+{
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 2; // block type 2
+
+ // pad with non-zero random bytes
+ word32 padLen = pkcsBlockLen - inputLen - 1;
+ rng.GenerateBlock(&pkcsBlock[1], padLen);
+ for (word32 i = 1; i < padLen; i++)
+ if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+ byte *output) const
+{
+ bool invalid = false;
+ unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 2.
+ invalid = (pkcsBlock[0] != 2) || invalid;
+
+ // skip past the padding until we find the separator
+ unsigned i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ unsigned int outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ memcpy (output, pkcsBlock+i, outputLen);
+ return outputLen;
+}
+
+
+void RSA_BlockType1::Pad(const byte* input, word32 inputLen, byte* pkcsBlock,
+ word32 pkcsBlockLen, RandomNumberGenerator&) const
+{
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 1; // block type 1 for SSL
+
+ // pad with 0xff bytes
+ memset(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+
+word32 RSA_BlockType1::UnPad(const byte* pkcsBlock, word32 pkcsBlockLen,
+ byte* output) const
+{
+ bool invalid = false;
+ unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 1 for SSL.
+ invalid = (pkcsBlock[0] != 1) || invalid;
+
+ // skip past the padding until we find the separator
+ unsigned i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ unsigned int outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ memcpy(output, pkcsBlock+i, outputLen);
+ return outputLen;
+}
+
+
+word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain)
+{
+ PK_Lengths lengths(key.GetModulus());
+
+ ByteBlock paddedBlock(BitsToBytes(lengths.PaddedBlockBitLength()));
+ Integer x = key.ApplyFunction(Integer(sig,
+ lengths.FixedCiphertextLength()));
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero();
+ x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
+ return RSA_BlockType1().UnPad(paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), plain);
+}
+
+#ifdef __GNUC__
+template AllocatorWithCleanup<unsigned char>::pointer StdReallocate<unsigned char, AllocatorWithCleanup<unsigned char> >(AllocatorWithCleanup<unsigned char>&, unsigned char*, AllocatorWithCleanup<unsigned char>::size_type, AllocatorWithCleanup<unsigned char>::size_type, bool);
+template AllocatorWithCleanup<unsigned int>::pointer StdReallocate<unsigned int, AllocatorWithCleanup<unsigned int> >(AllocatorWithCleanup<unsigned int>&, unsigned int*, AllocatorWithCleanup<unsigned int>::size_type, AllocatorWithCleanup<unsigned int>::size_type, bool);
+template class AbstractGroup<Integer>;
+template class AbstractRing<Integer>;
+template class RSA_Decryptor<RSA_BlockType2>;
+template class RSA_Encryptor<RSA_BlockType1>;
+template class RSA_Encryptor<RSA_BlockType2>;
+#endif
+
+} // namespace
+
+#ifdef __GNUC__
+namespace mySTL {
+template TaoCrypt::Integer* uninit_copy<TaoCrypt::Integer*, TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*);
+template TaoCrypt::Integer* uninit_fill_n<TaoCrypt::Integer*, unsigned int, TaoCrypt::Integer>(TaoCrypt::Integer*, unsigned int, TaoCrypt::Integer const&);
+template TaoCrypt::WindowSlider* uninit_copy<TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
+template vector<TaoCrypt::Integer>* uninit_fill_n<vector<TaoCrypt::Integer>*, unsigned int, vector<TaoCrypt::Integer> >(vector<TaoCrypt::Integer>*, unsigned int, vector<TaoCrypt::Integer> const&);
+template void destroy<TaoCrypt::Integer*>(TaoCrypt::Integer*, TaoCrypt::Integer*);
+template void destroy<TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
+template void destroy<vector<TaoCrypt::Integer>*>(vector<TaoCrypt::Integer>*, vector<TaoCrypt::Integer>*);
+}
+#endif
+
+
diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp
new file mode 100644
index 00000000000..4dfd2c3f3db
--- /dev/null
+++ b/extra/yassl/taocrypt/src/sha.cpp
@@ -0,0 +1,144 @@
+/* sha.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's sha.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include <string.h>
+#include "algorithm.hpp" // mySTL::swap
+#include "sha.hpp"
+
+
+namespace TaoCrypt {
+
+#define blk0(i) (W[i] = (*reinterpret_cast<word32*>(&buffer_[i*4])))
+#define blk1(i) (W[i&15] = \
+ rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
+
+#define f1(x,y,z) (z^(x &(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+// (R0+R1), R2, R3, R4 are the different operations used in SHA1
+#define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+
+
+void SHA::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xEFCDAB89L;
+ digest_[2] = 0x98BADCFEL;
+ digest_[3] = 0x10325476L;
+ digest_[4] = 0xC3D2E1F0L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+SHA::SHA(const SHA& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+SHA& SHA::operator= (const SHA& that)
+{
+ SHA tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void SHA::Swap(SHA& other)
+{
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(buffLen_, other.buffLen_);
+ mySTL::swap(digest_, other.digest_);
+ mySTL::swap(length_, other.length_);
+}
+
+
+void SHA::Transform()
+{
+ word32 W[BLOCK_SIZE / sizeof(word32)];
+
+ // Copy context->state[] to working vars
+ word32 a = digest_[0];
+ word32 b = digest_[1];
+ word32 c = digest_[2];
+ word32 d = digest_[3];
+ word32 e = digest_[4];
+
+ // 4 rounds of 20 operations each. Loop unrolled.
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ // Add the working vars back into digest state[]
+ digest_[0] += a;
+ digest_[1] += b;
+ digest_[2] += c;
+ digest_[3] += d;
+ digest_[4] += e;
+
+ // Wipe variables
+ a = b = c = d = e = 0;
+ memset(W, 0, sizeof(W));
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp
new file mode 100644
index 00000000000..115ad0cb272
--- /dev/null
+++ b/extra/yassl/taocrypt/taocrypt.dsp
@@ -0,0 +1,260 @@
+# Microsoft Developer Studio Project File - Name="taocrypt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=taocrypt - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "taocrypt.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "taocrypt.mak" CFG="taocrypt - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "taocrypt - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "taocrypt - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "taocrypt - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "taocrypt___Win32_Release"
+# PROP BASE Intermediate_Dir "taocrypt___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX- /O2 /I "include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "taocrypt - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "taocrypt___Win32_Debug"
+# PROP BASE Intermediate_Dir "taocrypt___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "taocrypt - Win32 Release"
+# Name "taocrypt - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\aes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aestables.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\algebra.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\arc4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\asn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\coding.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\des.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\dh.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\dsa.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\file.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\hash.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\integer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\md2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\md5.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\random.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ripemd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\rsa.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sha.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\aes.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\algebra.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arc4.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\asn.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\block.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\coding.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\des.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\dh.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\dsa.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\error.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\file.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hash.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hmac.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\integer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\md2.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\md5.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\misc.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\modarith.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\modes.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\random.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\ripemd.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\rsa.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\sha.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extra/yassl/taocrypt/taocrypt.dsw b/extra/yassl/taocrypt/taocrypt.dsw
new file mode 100644
index 00000000000..d10d7534c3d
--- /dev/null
+++ b/extra/yassl/taocrypt/taocrypt.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "taocrypt"=.\taocrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "test"=.\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extra/yassl/yassl.dsp b/extra/yassl/yassl.dsp
new file mode 100644
index 00000000000..f51c19eebbf
--- /dev/null
+++ b/extra/yassl/yassl.dsp
@@ -0,0 +1,192 @@
+# Microsoft Developer Studio Project File - Name="yassl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=yassl - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "yassl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "yassl.mak" CFG="yassl - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "yassl - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "yassl - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "yassl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX- /O2 /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "yassl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "yassl - Win32 Release"
+# Name "yassl - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\buffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\cert_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\crypto_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\handshake.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\lock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\log.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\socket_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ssl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\timer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_imp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_int.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\buffer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\cert_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\crypto_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\factory.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\handshake.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lock.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\log.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\socket_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\timer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_error.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_imp.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_int.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_types.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extra/yassl/yassl.dsw b/extra/yassl/yassl.dsw
new file mode 100644
index 00000000000..c0bba9acdce
--- /dev/null
+++ b/extra/yassl/yassl.dsw
@@ -0,0 +1,137 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "client"=.\examples\client\client.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoclient"=.\examples\echoclient\echoclient.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoserver"=.\examples\echoserver\echoserver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "server"=.\examples\server\server.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "taocrypt"=.\taocrypt\taocrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "test"=.\taocrypt\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testsuite"=.\testsuite\testsuite.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "yassl"=.\yassl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index 52a250bd7af..7f02eb587a8 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -635,13 +635,12 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
key+= 2; /* skip key pack length */
if (cs->mbmaxlen > 1)
{
- uint char_length= seg->length / cs->mbmaxlen;
- char_length_key= my_charpos(cs, key, key + char_length_key,
- char_length);
- set_if_smaller(char_length_key, seg->length);
- char_length_rec= my_charpos(cs, pos, pos + char_length_rec,
- char_length);
- set_if_smaller(char_length_rec, seg->length);
+ uint char_length1, char_length2;
+ char_length1= char_length2= seg->length / cs->mbmaxlen;
+ char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
+ set_if_smaller(char_length_key, char_length1);
+ char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
+ set_if_smaller(char_length_rec, char_length2);
}
if (cs->coll->strnncollsp(seg->charset,
diff --git a/include/config-win.h b/include/config-win.h
index bc392ce73d8..a4f81a0ec6a 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -106,20 +106,33 @@ functions */
/* Type information */
+#if defined(__EMX__) || !defined(HAVE_UINT)
+#undef HAVE_UINT
+#define HAVE_UINT
typedef unsigned short ushort;
typedef unsigned int uint;
+#endif /* defined(__EMX__) || !defined(HAVE_UINT) */
+
typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */
typedef __int64 longlong;
+#ifndef HAVE_SIGSET_T
typedef int sigset_t;
+#endif
#define longlong_defined
-/* off_t should not be __int64 because of conflicts in header files;
- Use my_off_t or os_off_t instead */
+/*
+ off_t should not be __int64 because of conflicts in header files;
+ Use my_off_t or os_off_t instead
+*/
+#ifndef HAVE_OFF_T
typedef long off_t;
+#endif
typedef __int64 os_off_t;
#ifdef _WIN64
typedef UINT_PTR rf_SetTimer;
#else
+#ifndef HAVE_SIZE_T
typedef unsigned int size_t;
+#endif
typedef uint rf_SetTimer;
#endif
diff --git a/include/decimal.h b/include/decimal.h
index 7b49841ca88..2648e04c1cf 100644
--- a/include/decimal.h
+++ b/include/decimal.h
@@ -39,7 +39,7 @@ int decimal2longlong(decimal_t *from, longlong *to);
int longlong2decimal(longlong from, decimal_t *to);
int decimal2double(decimal_t *from, double *to);
int double2decimal(double from, decimal_t *to);
-void decimal_optimize_fraction(decimal_t *from);
+int decimal_actual_fraction(decimal_t *from);
int decimal2bin(decimal_t *from, char *to, int precision, int scale);
int bin2decimal(char *from, decimal_t *to, int precision, int scale);
diff --git a/include/errmsg.h b/include/errmsg.h
index ae3b04b4f3a..fd3da392df4 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -95,6 +95,7 @@ extern const char *client_errors[]; /* Error messages */
#define CR_FETCH_CANCELED 2050
#define CR_NO_DATA 2051
#define CR_NO_STMT_METADATA 2052
-#define CR_ERROR_LAST /*Copy last error nr:*/ 2052
+#define CR_NO_RESULT_SET 2053
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2053
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 61524dc4ddd..6f304f4ba43 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -132,6 +132,7 @@ typedef struct my_collation_handler_st
/* Hash calculation */
void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len,
ulong *nr1, ulong *nr2);
+ my_bool (*propagate)(struct charset_info_st *cs, const uchar *str, uint len);
} MY_COLLATION_HANDLER;
extern MY_COLLATION_HANDLER my_collation_mb_bin_handler;
@@ -385,6 +386,10 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
extern my_bool my_parse_charset_xml(const char *bug, uint len,
int (*add)(CHARSET_INFO *cs));
+my_bool my_propagate_simple(CHARSET_INFO *cs, const uchar *str, uint len);
+my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, uint len);
+
+
#define _MY_U 01 /* Upper case */
#define _MY_L 02 /* Lower case */
#define _MY_NMR 04 /* Numeral (digit) */
diff --git a/include/my_global.h b/include/my_global.h
index 74846fe1762..5448aa3e871 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -43,6 +43,11 @@
#define HAVE_ERRNO_AS_DEFINE
#endif /* __CYGWIN__ */
+/* Determine when to use "#pragma interface" */
+#if !defined(__CYGWIN__) && !defined(__ICC) && defined(__GNUC__) && (__GNUC__ < 3)
+#define USE_PRAGMA_INTERFACE
+#endif
+
#if defined(i386) && !defined(__i386__)
#define __i386__
#endif
@@ -230,34 +235,11 @@ C_MODE_END
#define __LONG_MAX__ 2147483647
#endif
-/* Fix problem when linking c++ programs with gcc 3.x */
-#ifdef DEFINE_CXA_PURE_VIRTUAL
-#define FIX_GCC_LINKING_PROBLEM \
-C_MODE_START int __cxa_pure_virtual() {\
- DBUG_ASSERT("Pure virtual method called." == "Aborted");\
- return 0;\
-} C_MODE_END
-#else
-#define FIX_GCC_LINKING_PROBLEM
-#endif
-
/* egcs 1.1.2 has a problem with memcpy on Alpha */
#if defined(__GNUC__) && defined(__alpha__) && ! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
#define BAD_MEMCPY
#endif
-/* In Linux-alpha we have atomic.h if we are using gcc */
-#if defined(TARGET_OS_LINUX) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD)
-#define HAVE_ATOMIC_ADD
-#define HAVE_ATOMIC_SUB
-#endif
-
-/* In Linux-ia64 including atomic.h will give us an error */
-#if (defined(TARGET_OS_LINUX) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD)
-#undef HAVE_ATOMIC_ADD
-#undef HAVE_ATOMIC_SUB
-#endif
-
#if defined(_lint) && !defined(lint)
#define lint
#endif
@@ -326,9 +308,15 @@ C_MODE_START int __cxa_pure_virtual() {\
#ifndef CONFIG_SMP
#define CONFIG_SMP
#endif
+#if defined(__ia64__)
+#define new my_arg_new
+#endif
C_MODE_START
#include <asm/atomic.h>
C_MODE_END
+#if defined(__ia64__)
+#undef new
+#endif
#endif
#include <errno.h> /* Recommended by debian */
/* We need the following to go around a problem with openssl on solaris */
@@ -425,6 +413,8 @@ int __void__;
#endif
#if defined(__EMX__) || !defined(HAVE_UINT)
+#undef HAVE_UINT
+#define HAVE_UINT
typedef unsigned int uint;
typedef unsigned short ushort;
#endif
diff --git a/include/my_handler.h b/include/my_handler.h
index cad15d5471f..c076ba0c2c9 100644
--- a/include/my_handler.h
+++ b/include/my_handler.h
@@ -72,10 +72,11 @@ typedef struct st_HA_KEYSEG /* Key-portion */
#define set_rec_bits(bits, bit_ptr, bit_ofs, bit_len) \
{ \
- (bit_ptr)[0]= ((bit_ptr)[0] & ((1 << (bit_ofs)) - 1)) | \
+ (bit_ptr)[0]= ((bit_ptr)[0] & ~(((1 << (bit_len)) - 1) << (bit_ofs))) | \
((bits) << (bit_ofs)); \
if ((bit_ofs) + (bit_len) > 8) \
- (bit_ptr)[1]= ((bits) & ((1 << (bit_len)) - 1)) >> (8 - (bit_ofs)); \
+ (bit_ptr)[1]= ((bit_ptr)[1] & ~((1 << ((bit_len) - 8 + (bit_ofs))) - 1)) | \
+ ((bits) >> (8 - (bit_ofs))); \
}
#define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \
diff --git a/include/my_sys.h b/include/my_sys.h
index f63743a4c6c..f235b5a072e 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -179,6 +179,10 @@ extern void my_large_free(gptr ptr, myf my_flags);
#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43)
#pragma alloca
#endif /* _AIX */
+#if defined(__MWERKS__)
+#undef alloca
+#define alloca __alloca
+#endif /* __MWERKS__ */
#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && ! defined(alloca)
#define alloca __builtin_alloca
#endif /* GNUC */
@@ -638,6 +642,7 @@ extern uint dirname_part(my_string to,const char *name);
extern uint dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A))
extern int test_if_hard_path(const char *dir_name);
+extern my_bool has_path(const char *name);
extern char *convert_dirname(char *to, const char *from, const char *from_end);
extern void to_unix_path(my_string name);
extern my_string fn_ext(const char *name);
@@ -781,6 +786,7 @@ extern int my_search_option_files(const char *conf_file, int *argc,
char ***argv, uint *args_used,
Process_option_func func, void *func_ctx);
extern void free_defaults(char **argv);
+extern void my_print_default_files(const char *conf_file);
extern void print_defaults(const char *conf_file, const char **groups);
extern my_bool my_compress(byte *, ulong *, ulong *);
extern my_bool my_uncompress(byte *, ulong *, ulong *);
diff --git a/include/raid.h b/include/raid.h
index 04c54393e54..c840afcbaab 100644
--- a/include/raid.h
+++ b/include/raid.h
@@ -89,7 +89,7 @@ extern "C" {
#ifdef __cplusplus
}
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/include/violite.h b/include/violite.h
index 97784694e79..48046346f8c 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -87,7 +87,7 @@ my_bool vio_peer_addr(Vio* vio, char *buf, uint16 *port);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
my_bool vio_poll_read(Vio *vio,uint timeout);
-void vio_timeout(Vio *vio,uint timeout);
+void vio_timeout(Vio *vio,uint which, uint timeout);
#ifdef HAVE_OPENSSL
#include <openssl/opensslv.h>
@@ -99,6 +99,7 @@ void vio_timeout(Vio *vio,uint timeout);
#endif
#define HEADER_DES_LOCL_H dummy_something
+#define YASSL_MYSQL_COMPATIBLE
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -155,7 +156,7 @@ int vio_close_shared_memory(Vio * vio);
#define vio_close(vio) ((vio)->vioclose)(vio)
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
-#define vio_timeout(vio, seconds) (vio)->timeout(vio, seconds)
+#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds)
#endif /* !defined(DONT_MAP_VIO) */
/* This enumerator is used in parser - should be always visible */
@@ -198,7 +199,7 @@ struct st_vio
void (*in_addr)(Vio*, struct in_addr*);
my_bool (*should_retry)(Vio*);
int (*vioclose)(Vio*);
- void (*timeout)(Vio*, unsigned int timeout);
+ void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
void *ssl_arg;
#ifdef HAVE_SMEM
HANDLE handle_file_map;
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 710c945375c..45a81a4ac77 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -565,8 +565,15 @@ lock_rec_print(
Prints info of locks for all transactions. */
void
-lock_print_info(
-/*============*/
+lock_print_info_summary(
+/*====================*/
+ FILE* file); /* in: file where to print */
+/*************************************************************************
+Prints info of locks for each transaction. */
+
+void
+lock_print_info_all_transactions(
+/*=============================*/
FILE* file); /* in: file where to print */
/*************************************************************************
Validates the lock queue on a table. */
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 4a1833a1a21..6e4241965c1 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -466,8 +466,13 @@ Outputs to a file the output of the InnoDB Monitor. */
void
srv_printf_innodb_monitor(
/*======================*/
- FILE* file); /* in: output stream */
-/************************************************************************
+ FILE* file, /* in: output stream */
+ ulint* trx_start, /* out: file position of the start of
+ the list of active transactions */
+ ulint* trx_end); /* out: file position of the end of
+ the list of active transactions */
+
+/**********************************************************************
Function to pass InnoDB status variables to MySQL */
void
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 512f487b3f5..73ecc717e0e 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -4226,21 +4226,10 @@ lock_get_n_rec_locks(void)
Prints info of locks for all transactions. */
void
-lock_print_info(
-/*============*/
+lock_print_info_summary(
+/*====================*/
FILE* file) /* in: file where to print */
{
- lock_t* lock;
- trx_t* trx;
- ulint space;
- ulint page_no;
- page_t* page;
- ibool load_page_first = TRUE;
- ulint nth_trx = 0;
- ulint nth_lock = 0;
- ulint i;
- mtr_t mtr;
-
/* We must protect the MySQL thd->query field with a MySQL mutex, and
because the MySQL mutex must be reserved before the kernel_mutex of
InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */
@@ -4279,6 +4268,26 @@ lock_print_info(
fprintf(file,
"Total number of lock structs in row lock hash table %lu\n",
(ulong) lock_get_n_rec_locks());
+}
+
+/*************************************************************************
+Prints info of locks for each transaction. */
+
+void
+lock_print_info_all_transactions(
+/*=============================*/
+ FILE* file) /* in: file where to print */
+{
+ lock_t* lock;
+ ulint space;
+ ulint page_no;
+ page_t* page;
+ ibool load_page_first = TRUE;
+ ulint nth_trx = 0;
+ ulint nth_lock = 0;
+ ulint i;
+ mtr_t mtr;
+ trx_t* trx;
fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index a4bfdb6162d..f901425a5f9 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -1602,7 +1602,11 @@ Outputs to a file the output of the InnoDB Monitor. */
void
srv_printf_innodb_monitor(
/*======================*/
- FILE* file) /* in: output stream */
+ FILE* file, /* in: output stream */
+ ulint* trx_start, /* out: file position of the start of
+ the list of active transactions */
+ ulint* trx_end) /* out: file position of the end of
+ the list of active transactions */
{
double time_elapsed;
time_t current_time;
@@ -1651,7 +1655,24 @@ srv_printf_innodb_monitor(
mutex_exit(&dict_foreign_err_mutex);
- lock_print_info(file);
+ lock_print_info_summary(file);
+ if (trx_start) {
+ long t = ftell(file);
+ if (t < 0) {
+ *trx_start = ULINT_UNDEFINED;
+ } else {
+ *trx_start = (ulint) t;
+ }
+ }
+ lock_print_info_all_transactions(file);
+ if (trx_end) {
+ long t = ftell(file);
+ if (t < 0) {
+ *trx_end = ULINT_UNDEFINED;
+ } else {
+ *trx_end = (ulint) t;
+ }
+ }
fputs("--------\n"
"FILE I/O\n"
"--------\n", file);
@@ -1865,13 +1886,13 @@ loop:
last_monitor_time = time(NULL);
if (srv_print_innodb_monitor) {
- srv_printf_innodb_monitor(stderr);
+ srv_printf_innodb_monitor(stderr, NULL, NULL);
}
if (srv_innodb_status) {
mutex_enter(&srv_monitor_file_mutex);
rewind(srv_monitor_file);
- srv_printf_innodb_monitor(srv_monitor_file);
+ srv_printf_innodb_monitor(srv_monitor_file, NULL, NULL);
os_file_set_eof(srv_monitor_file);
mutex_exit(&srv_monitor_file_mutex);
}
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 90ad3aefaca..5d183b478ef 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -80,6 +80,7 @@ const char *client_errors[]=
"Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch",
"Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the statement",
""
};
@@ -141,6 +142,7 @@ const char *client_errors[]=
"Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch",
"Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the statement",
""
};
@@ -200,6 +202,7 @@ const char *client_errors[]=
"Row retrieval was canceled by mysql_stmt_close() call",
"Attempt to read column without prior row fetch",
"Prepared statement contains no metadata",
+ "Attempt to read a row while there is no result set associated with the statement",
""
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index bf797dfd580..3e6b29b7602 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1724,6 +1724,13 @@ static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
static my_bool setup_one_fetch_function(MYSQL_BIND *bind, MYSQL_FIELD *field);
+/* Auxilary function used to reset statement handle. */
+
+#define RESET_SERVER_SIDE 1
+#define RESET_LONG_DATA 2
+
+static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
+
/*
Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
values stored in network buffer.
@@ -2019,7 +2026,8 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
/* This is second prepare with another statement */
char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
- mysql_stmt_free_result(stmt);
+ if (reset_stmt_handle(stmt, RESET_LONG_DATA))
+ DBUG_RETURN(1);
/*
These members must be reset for API to
function in case of error or misuse.
@@ -2702,12 +2710,8 @@ static int
stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
unsigned char **row __attribute__((unused)))
{
- if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
- {
- set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate);
- return 1;
- }
- return MYSQL_NO_DATA;
+ set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate);
+ return 1;
}
@@ -2817,7 +2821,8 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
DBUG_RETURN(1);
}
- mysql_stmt_free_result(stmt);
+ if (reset_stmt_handle(stmt, 0))
+ DBUG_RETURN(1);
/*
No need to check for stmt->state: if the statement wasn't
prepared we'll get 'unknown statement handler' error from server.
@@ -4805,16 +4810,21 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
DBUG_RETURN(stmt->result.rows);
}
-my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
-{
- MYSQL_DATA *result= &stmt->result;
- DBUG_ENTER("mysql_stmt_free_result");
- DBUG_ASSERT(stmt != 0);
+/*
+ Free the client side memory buffers, reset long data state
+ on client if necessary, and reset the server side statement if
+ this has been requested.
+*/
+static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
+{
+ /* If statement hasn't been prepared there is nothing to reset */
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
MYSQL *mysql= stmt->mysql;
+ MYSQL_DATA *result= &stmt->result;
+ my_bool has_cursor= stmt->read_row_func == stmt_read_row_from_cursor;
if (result->data)
{
@@ -4824,23 +4834,58 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
result->rows= 0;
stmt->data_cursor= NULL;
}
-
- if (mysql && stmt->field_count &&
- (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
+ if (flags & RESET_LONG_DATA)
{
- if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
- mysql->unbuffered_fetch_owner= 0;
- if (mysql->status != MYSQL_STATUS_READY)
+ MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count;
+ /* Clear long_data_used flags */
+ for (; param < param_end; param++)
+ param->long_data_used= 0;
+ }
+ stmt->read_row_func= stmt_read_row_no_data;
+ if (mysql)
+ {
+ if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
{
- /* There is a result set and it belongs to this statement */
- (*mysql->methods->flush_use_result)(mysql);
- mysql->status= MYSQL_STATUS_READY;
+ if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
+ mysql->unbuffered_fetch_owner= 0;
+ if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
+ {
+ /* There is a result set and it belongs to this statement */
+ (*mysql->methods->flush_use_result)(mysql);
+ if (mysql->unbuffered_fetch_owner)
+ *mysql->unbuffered_fetch_owner= TRUE;
+ mysql->status= MYSQL_STATUS_READY;
+ }
+ }
+ if (has_cursor || (flags & RESET_SERVER_SIDE))
+ {
+ /*
+ Reset the server side statement and close the server side
+ cursor if it exists.
+ */
+ char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
+ int4store(buff, stmt->stmt_id);
+ if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
+ sizeof(buff), 0, 0, 0))
+ {
+ set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
+ mysql->net.sqlstate);
+ stmt->state= MYSQL_STMT_INIT_DONE;
+ return 1;
+ }
}
}
stmt->state= MYSQL_STMT_PREPARE_DONE;
- stmt->read_row_func= stmt_read_row_no_data;
}
- DBUG_RETURN(0);
+ return 0;
+}
+
+my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
+{
+ DBUG_ENTER("mysql_stmt_free_result");
+
+ /* Free the client side and close the server side cursor if there is one */
+ DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA));
}
/********************************************************************
@@ -4913,33 +4958,10 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
{
- char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
- MYSQL *mysql;
- MYSQL_BIND *param, *param_end;
DBUG_ENTER("mysql_stmt_reset");
DBUG_ASSERT(stmt != 0);
-
- /* If statement hasnt been prepared there is nothing to reset */
- if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
- DBUG_RETURN(0);
-
- mysql= stmt->mysql->last_used_con;
- int4store(buff, stmt->stmt_id); /* Send stmt id to server */
- if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
- sizeof(buff), 0, 0, 0))
- {
- set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
- mysql->net.sqlstate);
- DBUG_RETURN(1);
- }
-
- /* Clear long_data_used for next call (as we do in mysql_stmt_execute() */
- for (param= stmt->params, param_end= param + stmt->param_count;
- param < param_end;
- param++)
- param->long_data_used= 0;
-
- DBUG_RETURN(0);
+ /* Reset the client and server sides of the prepared statement */
+ DBUG_RETURN(reset_stmt_handle(stmt, RESET_SERVER_SIDE | RESET_LONG_DATA));
}
/*
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 5d88497e561..414ac4afd85 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -149,3 +149,6 @@ EXPORTS
mysql_server_init
mysql_server_end
get_defaults_files
+ get_charset_by_csname
+ get_charsets_dir
+ charsets_dir
diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc
index 2d3d82b7952..ecc45096165 100644
--- a/libmysqld/emb_qcache.cc
+++ b/libmysqld/emb_qcache.cc
@@ -22,7 +22,7 @@
void Querycache_stream::store_char(char c)
{
if (data_end == cur_data)
- use_next_block();
+ use_next_block(TRUE);
*(cur_data++)= c;
#ifndef DBUG_OFF
stored_size++;
@@ -42,13 +42,13 @@ void Querycache_stream::store_short(ushort s)
}
if (data_end == cur_data)
{
- use_next_block();
+ use_next_block(TRUE);
int2store(cur_data, s);
cur_data+= 2;
return;
}
*cur_data= ((byte *)(&s))[0];
- use_next_block();
+ use_next_block(TRUE);
*(cur_data++)= ((byte *)(&s))[1];
}
@@ -66,7 +66,7 @@ void Querycache_stream::store_int(uint i)
}
if (!rest_len)
{
- use_next_block();
+ use_next_block(TRUE);
int4store(cur_data, i);
cur_data+= 4;
return;
@@ -74,7 +74,7 @@ void Querycache_stream::store_int(uint i)
char buf[4];
int4store(buf, i);
memcpy(cur_data, buf, rest_len);
- use_next_block();
+ use_next_block(TRUE);
memcpy(cur_data, buf+rest_len, 4-rest_len);
cur_data+= 4-rest_len;
}
@@ -93,13 +93,13 @@ void Querycache_stream::store_ll(ulonglong ll)
}
if (!rest_len)
{
- use_next_block();
+ use_next_block(TRUE);
int8store(cur_data, ll);
cur_data+= 8;
return;
}
memcpy(cur_data, &ll, rest_len);
- use_next_block();
+ use_next_block(TRUE);
memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len);
cur_data+= 8-rest_len;
}
@@ -112,14 +112,14 @@ void Querycache_stream::store_str_only(const char *str, uint str_len)
do
{
size_t rest_len= data_end - cur_data;
- if (rest_len > str_len)
+ if (rest_len >= str_len)
{
memcpy(cur_data, str, str_len);
cur_data+= str_len;
return;
}
memcpy(cur_data, str, rest_len);
- use_next_block();
+ use_next_block(TRUE);
str_len-= rest_len;
str+= rest_len;
} while(str_len);
@@ -145,7 +145,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len)
char Querycache_stream::load_char()
{
if (cur_data == data_end)
- use_next_block();
+ use_next_block(FALSE);
return *(cur_data++);
}
@@ -160,13 +160,13 @@ ushort Querycache_stream::load_short()
}
if (data_end == cur_data)
{
- use_next_block();
+ use_next_block(FALSE);
result= uint2korr(cur_data);
cur_data+= 2;
return result;
}
((byte*)&result)[0]= *cur_data;
- use_next_block();
+ use_next_block(FALSE);
((byte*)&result)[1]= *(cur_data++);
return result;
}
@@ -183,14 +183,14 @@ uint Querycache_stream::load_int()
}
if (!rest_len)
{
- use_next_block();
+ use_next_block(FALSE);
result= uint4korr(cur_data);
cur_data+= 4;
return result;
}
char buf[4];
memcpy(buf, cur_data, rest_len);
- use_next_block();
+ use_next_block(FALSE);
memcpy(buf+rest_len, cur_data, 4-rest_len);
cur_data+= 4-rest_len;
result= uint4korr(buf);
@@ -209,13 +209,13 @@ ulonglong Querycache_stream::load_ll()
}
if (!rest_len)
{
- use_next_block();
+ use_next_block(FALSE);
result= uint8korr(cur_data);
cur_data+= 8;
return result;
}
memcpy(&result, cur_data, rest_len);
- use_next_block();
+ use_next_block(FALSE);
memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len);
cur_data+= 8-rest_len;
return result;
@@ -226,7 +226,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
do
{
size_t rest_len= data_end - cur_data;
- if (rest_len > str_len)
+ if (rest_len >= str_len)
{
memcpy(buffer, cur_data, str_len);
cur_data+= str_len;
@@ -234,7 +234,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
break;
}
memcpy(buffer, cur_data, rest_len);
- use_next_block();
+ use_next_block(FALSE);
str_len-= rest_len;
buffer+= rest_len;
} while(str_len);
diff --git a/libmysqld/emb_qcache.h b/libmysqld/emb_qcache.h
index 32ce19847ff..6201058ce56 100644
--- a/libmysqld/emb_qcache.h
+++ b/libmysqld/emb_qcache.h
@@ -22,22 +22,43 @@ class Querycache_stream
uint headers_len;
public:
#ifndef DBUG_OFF
+ Query_cache_block *first_block;
uint stored_size;
#endif
Querycache_stream(Query_cache_block *ini_block, uint ini_headers_len) :
block(ini_block), headers_len(ini_headers_len)
{
- use_next_block();
+ cur_data= ((byte*)block)+headers_len;
+ data_end= cur_data + (block->used-headers_len);
#ifndef DBUG_OFF
+ first_block= ini_block;
stored_size= 0;
#endif
}
- void use_next_block()
+ void use_next_block(bool writing)
{
+ /*
+ This shouldn't be called if there is only one block, or to loop
+ around to the first block again. That means we're trying to write
+ more data than we allocated space for.
+ */
+ DBUG_ASSERT(block->next != block);
+ DBUG_ASSERT(block->next != first_block);
+
+ block= block->next;
+ /*
+ While writing, update the type of each block as we write to it.
+ While reading, make sure that the block is of the expected type.
+ */
+ if (writing)
+ block->type= Query_cache_block::RES_CONT;
+ else
+ DBUG_ASSERT(block->type == Query_cache_block::RES_CONT);
+
cur_data= ((byte*)block)+headers_len;
data_end= cur_data + (block->used-headers_len);
}
-
+
void store_char(char c);
void store_short(ushort s);
void store_int(uint i);
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 6fa41fb3fd0..70074e44c6f 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -199,6 +199,14 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
unix_socket=0;
db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL;
+ /* Send client information for access check */
+ client_flag|=CLIENT_CAPABILITIES;
+ if (client_flag & CLIENT_MULTI_STATEMENTS)
+ client_flag|= CLIENT_MULTI_RESULTS;
+ client_flag&= ~CLIENT_COMPRESS;
+ if (db)
+ client_flag|=CLIENT_CONNECT_WITH_DB;
+
mysql->thd= create_embedded_thd(client_flag, db_name);
init_embedded_mysql(mysql, client_flag, db_name);
@@ -209,11 +217,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (mysql_init_charset(mysql))
goto error;
- /* Send client information for access check */
- client_flag|=CLIENT_CAPABILITIES;
- client_flag&= ~CLIENT_COMPRESS;
- if (db)
- client_flag|=CLIENT_CONNECT_WITH_DB;
mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
if (mysql->options.init_commands)
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 352c7954d72..74bb541b220 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -31,6 +31,7 @@
#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
#endif
#include <my_getopt.h>
+#include <assert.h>
#if INT_MAX > 32767
#define BITS_SAVED 32
@@ -1996,7 +1997,9 @@ static void write_bits (register ulong value, register uint bits)
{
reg3 uint byte_buff;
bits= (uint) -file_buffer.bits;
- byte_buff=file_buffer.current_byte | (uint) (value >> bits);
+ DBUG_ASSERT(bits <= 8 * sizeof(value));
+ byte_buff= (file_buffer.current_byte |
+ ((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0));
#if BITS_SAVED == 32
*file_buffer.pos++= (byte) (byte_buff >> 24) ;
*file_buffer.pos++= (byte) (byte_buff >> 16) ;
@@ -2004,7 +2007,9 @@ static void write_bits (register ulong value, register uint bits)
*file_buffer.pos++= (byte) (byte_buff >> 8) ;
*file_buffer.pos++= (byte) byte_buff;
- value&=(1 << bits)-1;
+ DBUG_ASSERT(bits <= 8 * sizeof(ulong));
+ if (bits != 8 * sizeof(value))
+ value&= (((ulong) 1) << bits) - 1;
#if BITS_SAVED == 16
if (bits >= sizeof(uint))
{
diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c
index a59ccb7d966..0dc2f4f9768 100644
--- a/myisammrg/myrg_open.c
+++ b/myisammrg/myrg_open.c
@@ -80,7 +80,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
continue; /* Skip comments */
}
- if (!test_if_hard_path(buff))
+ if (!has_path(buff))
{
VOID(strmake(name_buff+dir_length,buff,
sizeof(name_buff)-1-dir_length));
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 5fb4d99d4f4..1a648f98b1b 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -703,6 +703,12 @@ then
fi
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT"
+# Need to pass additional arguments to MYSQL_CLIENT_TEST for embedded server
+# -A marks each argument for passing to the function which initializes the
+# embedded library
+if [ "x$USE_EMBEDDED_SERVER" = "x1" ]; then
+ MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST -A --language=$LANGUAGE -A --datadir=$SLAVE_MYDDIR -A --character-sets-dir=$CHARSETSDIR"
+fi
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
@@ -1181,6 +1187,7 @@ start_master()
--language=$LANGUAGE \
--innodb_data_file_path=ibdata1:128M:autoextend \
--open-files-limit=1024 \
+ --log-bin-trust-routine-creators \
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
@@ -1201,6 +1208,7 @@ start_master()
--tmpdir=$MYSQL_TMP_DIR \
--language=$LANGUAGE \
--innodb_data_file_path=ibdata1:128M:autoextend \
+ --log-bin-trust-routine-creators \
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
@@ -1333,6 +1341,7 @@ start_slave()
--report-port=$slave_port \
--master-retry-count=10 \
-O slave_net_timeout=10 \
+ --log-bin-trust-routine-creators \
$SMALL_SERVER \
$EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT"
CUR_MYERR=$slave_err
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index e372c307ba7..a0c8f317db2 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -128,3 +128,20 @@ t2.value64=t1.value64;
value64 value32 value64 value32
9223372036854775807 2 9223372036854775807 4
drop table t1, t2;
+create table t1 select 1 as 'a';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(1) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 select 9223372036854775809 as 'a';
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(19) unsigned NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t1;
+a
+9223372036854775809
+drop table t1;
diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result
index 66752b11655..38e548490fe 100644
--- a/mysql-test/r/blackhole.result
+++ b/mysql-test/r/blackhole.result
@@ -105,8 +105,8 @@ a
select * from t3;
a
show binlog events;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000001 # Start 1 # Server ver: VERSION, Binlog ver: 3
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
master-bin.000001 # Query 1 # use `test`; drop table t1,t2
master-bin.000001 # Query 1 # use `test`; create table t1 (a int) engine=blackhole
master-bin.000001 # Query 1 # use `test`; delete from t1 where a=10
@@ -115,8 +115,8 @@ master-bin.000001 # Query 1 # use `test`; insert into t1 values(1)
master-bin.000001 # Query 1 # use `test`; insert ignore into t1 values(1)
master-bin.000001 # Query 1 # use `test`; replace into t1 values(100)
master-bin.000001 # Query 1 # use `test`; create table t2 (a varchar(200)) engine=blackhole
-master-bin.000001 # Create_file 1 # db=test;table=t2;file_id=1;block_len=581
-master-bin.000001 # Exec_load 1 # ;file_id=1
+master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=581
+master-bin.000001 # Execute_load_query 1 # use `test`; load data infile '../../std_data/words.dat' into table t2 ;file_id=1
master-bin.000001 # Query 1 # use `test`; alter table t1 add b int
master-bin.000001 # Query 1 # use `test`; alter table t1 drop b
master-bin.000001 # Query 1 # use `test`; create table t3 like t1
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 1ca913e1259..5fb21004469 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -105,9 +105,9 @@ t1 CREATE TABLE `t1` (
`c4` varbinary(1) NOT NULL default '',
`c5` varbinary(4) NOT NULL default '',
`c6` varbinary(4) NOT NULL default '',
- `c7` decimal(5,1) NOT NULL default '0.0',
- `c8` decimal(5,1) NOT NULL default '0.0',
- `c9` decimal(5,1) default NULL,
+ `c7` decimal(2,1) NOT NULL default '0.0',
+ `c8` decimal(2,1) NOT NULL default '0.0',
+ `c9` decimal(2,1) default NULL,
`c10` double NOT NULL default '0',
`c11` double NOT NULL default '0',
`c12` varbinary(5) NOT NULL default ''
@@ -152,9 +152,9 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(1)` int(1) NOT NULL default '0',
- `COALESCE(1.0)` decimal(5,1) NOT NULL default '0.0',
+ `COALESCE(1.0)` decimal(2,1) NOT NULL default '0.0',
`COALESCE('a')` varchar(1) NOT NULL default '',
- `COALESCE(1,1.0)` decimal(5,1) NOT NULL default '0.0',
+ `COALESCE(1,1.0)` decimal(2,1) NOT NULL default '0.0',
`COALESCE(1,'1')` varbinary(1) NOT NULL default '',
`COALESCE(1.1,'1')` varbinary(4) NOT NULL default '',
`COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index feefd47c611..6dc608a9289 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -4,12 +4,11 @@ CAST(1-2 AS UNSIGNED)
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
-1
-select CONVERT('-1',UNSIGNED);
-CONVERT('-1',UNSIGNED)
-18446744073709551615
select CAST('10 ' as unsigned integer);
CAST('10 ' as unsigned integer)
10
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '10 '
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1
18446744073709551611 18446744073709551611
@@ -100,6 +99,41 @@ select 10E+0+'a';
10
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
+select cast('18446744073709551616' as unsigned);
+cast('18446744073709551616' as unsigned)
+18446744073709551615
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '18446744073709551616'
+select cast('18446744073709551616' as signed);
+cast('18446744073709551616' as signed)
+-1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '18446744073709551616'
+select cast('9223372036854775809' as signed);
+cast('9223372036854775809' as signed)
+-9223372036854775807
+Warnings:
+Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
+select cast('-1' as unsigned);
+cast('-1' as unsigned)
+18446744073709551615
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+select cast('abc' as signed);
+cast('abc' as signed)
+0
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'abc'
+select cast('1a' as signed);
+cast('1a' as signed)
+1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '1a'
+select cast('' as signed);
+cast('' as signed)
+0
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: ''
set names binary;
select cast(_latin1'test' as char character set latin2);
cast(_latin1'test' as char character set latin2)
@@ -255,6 +289,39 @@ timediff(cast('2004-12-30 12:00:00' as time), '12:00:00')
select timediff(cast('1 12:00:00' as time), '12:00:00');
timediff(cast('1 12:00:00' as time), '12:00:00')
24:00:00
+select cast(18446744073709551615 as unsigned);
+cast(18446744073709551615 as unsigned)
+18446744073709551615
+select cast(18446744073709551615 as signed);
+cast(18446744073709551615 as signed)
+-1
+select cast('18446744073709551615' as unsigned);
+cast('18446744073709551615' as unsigned)
+18446744073709551615
+select cast('18446744073709551615' as signed);
+cast('18446744073709551615' as signed)
+-1
+Warnings:
+Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
+select cast('9223372036854775807' as signed);
+cast('9223372036854775807' as signed)
+9223372036854775807
+select cast(concat('184467440','73709551615') as unsigned);
+cast(concat('184467440','73709551615') as unsigned)
+18446744073709551615
+select cast(concat('184467440','73709551615') as signed);
+cast(concat('184467440','73709551615') as signed)
+-1
+Warnings:
+Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
+select cast(repeat('1',20) as unsigned);
+cast(repeat('1',20) as unsigned)
+11111111111111111111
+select cast(repeat('1',20) as signed);
+cast(repeat('1',20) as signed)
+-7335632962598440505
+Warnings:
+Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
select cast('1.2' as decimal(3,2));
cast('1.2' as decimal(3,2))
1.20
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index ecaa13642bd..4c565f4f1b1 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -5,3 +5,12 @@ insert into t1 values (200000);
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
+Create table t1(f1 int);
+Create table t2(f1 int);
+Create view v1 as Select * from t1;
+Check Table v1,t2;
+Table Op Msg_type Msg_text
+test.v1 check status OK
+test.t2 check status OK
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 4f4400b4a9b..34ccab9bcc5 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -115,9 +115,9 @@ Field Type Null Key Default Extra
a datetime NO 0000-00-00 00:00:00
b time NO 00:00:00
c date NO 0000-00-00
-d int(2) NO 0
-e decimal(6,1) NO 0.0
-f bigint(18) NO 0
+d int(3) NO 0
+e decimal(3,1) NO 0.0
+f bigint(19) NO 0
drop table t2;
create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) as t, CAST("2001-12-29 20:45:11" AS DATETIME) as dt;
describe t2;
@@ -429,7 +429,7 @@ explain t2;
Field Type Null Key Default Extra
a int(11) YES NULL
b bigint(11) NO 0
-c bigint(10) NO 0
+c bigint(11) NO 0
d date YES NULL
e varchar(1) NO
f datetime YES NULL
@@ -448,12 +448,12 @@ Table Create Table
t2 CREATE TABLE `t2` (
`ifnull(a,a)` tinyint(4) default NULL,
`ifnull(b,b)` smallint(6) default NULL,
- `ifnull(c,c)` mediumint(9) default NULL,
+ `ifnull(c,c)` mediumint(8) default NULL,
`ifnull(d,d)` int(11) default NULL,
`ifnull(e,e)` bigint(20) default NULL,
- `ifnull(f,f)` float(3,2) default NULL,
- `ifnull(g,g)` double(4,3) default NULL,
- `ifnull(h,h)` decimal(6,4) default NULL,
+ `ifnull(f,f)` float(24,2) default NULL,
+ `ifnull(g,g)` double(53,3) default NULL,
+ `ifnull(h,h)` decimal(5,4) default NULL,
`ifnull(i,i)` year(4) default NULL,
`ifnull(j,j)` date default NULL,
`ifnull(k,k)` datetime NOT NULL default '0000-00-00 00:00:00',
@@ -568,3 +568,14 @@ NULL 1
Test 0
NULL 1
drop table t1, t2, t3;
+create table t1 (b bool not null default false);
+create table t2 (b bool not null default true);
+insert into t1 values ();
+insert into t2 values ();
+select * from t1;
+b
+0
+select * from t2;
+b
+1
+drop table t1,t2;
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index 43947edbd48..f60dc175cd6 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -338,3 +338,9 @@ ss
ss
ß
DROP TABLE t1;
+create table t1 (s1 char(5) character set latin1 collate latin1_german2_ci);
+insert into t1 values (0xf6) /* this is o-umlaut */;
+select * from t1 where length(s1)=1 and s1='oe';
+s1
+drop table t1;
diff --git a/mysql-test/r/ctype_latin2.result b/mysql-test/r/ctype_latin2.result
new file mode 100644
index 00000000000..c2c021b0760
--- /dev/null
+++ b/mysql-test/r/ctype_latin2.result
@@ -0,0 +1,383 @@
+drop table if exists t1;
+SET NAMES latin2;
+CREATE TABLE t1 (a char(1) character set latin2);
+INSERT INTO t1 VALUES (0x20),(0x21),(0x22),(0x23),(0x24),(0x25),(0x26),(0x27);
+INSERT INTO t1 VALUES (0x28),(0x29),(0x2A),(0x2B),(0x2C),(0x2D),(0x2E),(0x2F);
+INSERT INTO t1 VALUES (0x30),(0x31),(0x32),(0x33),(0x34),(0x35),(0x36),(0x37);
+INSERT INTO t1 VALUES (0x38),(0x39),(0x3A),(0x3B),(0x3C),(0x3D),(0x3E),(0x3F);
+INSERT INTO t1 VALUES (0x40),(0x41),(0x42),(0x43),(0x44),(0x45),(0x46),(0x47);
+INSERT INTO t1 VALUES (0x48),(0x49),(0x4A),(0x4B),(0x4C),(0x4D),(0x4E),(0x4F);
+INSERT INTO t1 VALUES (0x50),(0x51),(0x52),(0x53),(0x54),(0x55),(0x56),(0x57);
+INSERT INTO t1 VALUES (0x58),(0x59),(0x5A),(0x5B),(0x5C),(0x5D),(0x5E),(0x5F);
+INSERT INTO t1 VALUES (0x60),(0x61),(0x62),(0x63),(0x64),(0x65),(0x66),(0x67);
+INSERT INTO t1 VALUES (0x68),(0x69),(0x6A),(0x6B),(0x6C),(0x6D),(0x6E),(0x6F);
+INSERT INTO t1 VALUES (0x70),(0x71),(0x72),(0x73),(0x74),(0x75),(0x76),(0x77);
+INSERT INTO t1 VALUES (0x78),(0x79),(0x7A),(0x7B),(0x7C),(0x7D),(0x7E),(0x7F);
+INSERT INTO t1 VALUES (0x80),(0x81),(0x82),(0x83),(0x84),(0x85),(0x86),(0x87);
+INSERT INTO t1 VALUES (0x88),(0x89),(0x8A),(0x8B),(0x8C),(0x8D),(0x8E),(0x8F);
+INSERT INTO t1 VALUES (0x90),(0x91),(0x92),(0x93),(0x94),(0x95),(0x96),(0x97);
+INSERT INTO t1 VALUES (0x98),(0x99),(0x9A),(0x9B),(0x9C),(0x9D),(0x9E),(0x9F);
+INSERT INTO t1 VALUES (0xA0),(0xA1),(0xA2),(0xA3),(0xA4),(0xA5),(0xA6),(0xA7);
+INSERT INTO t1 VALUES (0xA8),(0xA9),(0xAA),(0xAB),(0xAC),(0xAD),(0xAE),(0xAF);
+INSERT INTO t1 VALUES (0xB0),(0xB1),(0xB2),(0xB3),(0xB4),(0xB5),(0xB6),(0xB7);
+INSERT INTO t1 VALUES (0xB8),(0xB9),(0xBA),(0xBB),(0xBC),(0xBD),(0xBE),(0xBF);
+INSERT INTO t1 VALUES (0xC0),(0xC1),(0xC2),(0xC3),(0xC4),(0xC5),(0xC6),(0xC7);
+INSERT INTO t1 VALUES (0xC8),(0xC9),(0xCA),(0xCB),(0xCC),(0xCD),(0xCE),(0xCF);
+INSERT INTO t1 VALUES (0xD0),(0xD1),(0xD2),(0xD3),(0xD4),(0xD5),(0xD6),(0xD7);
+INSERT INTO t1 VALUES (0xD8),(0xD9),(0xDA),(0xDB),(0xDC),(0xDD),(0xDE),(0xDF);
+INSERT INTO t1 VALUES (0xE0),(0xE1),(0xE2),(0xE3),(0xE4),(0xE5),(0xE6),(0xE7);
+INSERT INTO t1 VALUES (0xE8),(0xE9),(0xEA),(0xEB),(0xEC),(0xED),(0xEE),(0xEF);
+INSERT INTO t1 VALUES (0xF0),(0xF1),(0xF2),(0xF3),(0xF4),(0xF5),(0xF6),(0xF7);
+INSERT INTO t1 VALUES (0xF8),(0xF9),(0xFA),(0xFB),(0xFC),(0xFD),(0xFE),(0xFF);
+SELECT hex(a) ha, hex(lower(a)) hl, hex(upper(a)) hu,
+a, lower(a) l, upper(a) u from t1 order by ha;
+ha hl hu a l u
+
+21 21 21 ! ! !
+22 22 22 " " "
+23 23 23 # # #
+24 24 24 $ $ $
+25 25 25 % % %
+26 26 26 & & &
+27 27 27 ' ' '
+28 28 28 ( ( (
+29 29 29 ) ) )
+2A 2A 2A * * *
+2B 2B 2B + + +
+2C 2C 2C , , ,
+2D 2D 2D - - -
+2E 2E 2E . . .
+2F 2F 2F / / /
+30 30 30 0 0 0
+31 31 31 1 1 1
+32 32 32 2 2 2
+33 33 33 3 3 3
+34 34 34 4 4 4
+35 35 35 5 5 5
+36 36 36 6 6 6
+37 37 37 7 7 7
+38 38 38 8 8 8
+39 39 39 9 9 9
+3A 3A 3A : : :
+3B 3B 3B ; ; ;
+3C 3C 3C < < <
+3D 3D 3D = = =
+3E 3E 3E > > >
+3F 3F 3F ? ? ?
+40 40 40 @ @ @
+41 61 41 A a A
+42 62 42 B b B
+43 63 43 C c C
+44 64 44 D d D
+45 65 45 E e E
+46 66 46 F f F
+47 67 47 G g G
+48 68 48 H h H
+49 69 49 I i I
+4A 6A 4A J j J
+4B 6B 4B K k K
+4C 6C 4C L l L
+4D 6D 4D M m M
+4E 6E 4E N n N
+4F 6F 4F O o O
+50 70 50 P p P
+51 71 51 Q q Q
+52 72 52 R r R
+53 73 53 S s S
+54 74 54 T t T
+55 75 55 U u U
+56 76 56 V v V
+57 77 57 W w W
+58 78 58 X x X
+59 79 59 Y y Y
+5A 7A 5A Z z Z
+5B 5B 5B [ [ [
+5C 5C 5C \ \ \
+5D 5D 5D ] ] ]
+5E 5E 5E ^ ^ ^
+5F 5F 5F _ _ _
+60 60 60 ` ` `
+61 61 41 a a A
+62 62 42 b b B
+63 63 43 c c C
+64 64 44 d d D
+65 65 45 e e E
+66 66 46 f f F
+67 67 47 g g G
+68 68 48 h h H
+69 69 49 i i I
+6A 6A 4A j j J
+6B 6B 4B k k K
+6C 6C 4C l l L
+6D 6D 4D m m M
+6E 6E 4E n n N
+6F 6F 4F o o O
+70 70 50 p p P
+71 71 51 q q Q
+72 72 52 r r R
+73 73 53 s s S
+74 74 54 t t T
+75 75 55 u u U
+76 76 56 v v V
+77 77 57 w w W
+78 78 58 x x X
+79 79 59 y y Y
+7A 7A 5A z z Z
+7B 7B 7B { { {
+7C 7C 7C | | |
+7D 7D 7D } } }
+7E 7E 7E ~ ~ ~
+7F 7F 7F   
+80 80 80 € € €
+81 81 81
+82 82 82 ‚ ‚ ‚
+83 83 83 ƒ ƒ ƒ
+84 84 84 „ „ „
+85 85 85 … … …
+86 86 86 † † †
+87 87 87 ‡ ‡ ‡
+88 88 88 ˆ ˆ ˆ
+89 89 89 ‰ ‰ ‰
+8A 8A 8A Š Š Š
+8B 8B 8B ‹ ‹ ‹
+8C 8C 8C Œ Œ Œ
+8D 8D 8D
+8E 8E 8E Ž Ž Ž
+8F 8F 8F
+90 90 90
+91 91 91 ‘ ‘ ‘
+92 92 92 ’ ’ ’
+93 93 93 “ “ “
+94 94 94 ” ” ”
+95 95 95 • • •
+96 96 96 – – –
+97 97 97 — — —
+98 98 98 ˜ ˜ ˜
+99 99 99 ™ ™ ™
+9A 9A 9A š š š
+9B 9B 9B › › ›
+9C 9C 9C œ œ œ
+9D 9D 9D
+9E 9E 9E ž ž ž
+9F 9F 9F Ÿ Ÿ Ÿ
+A0 A0 A0      
+A1 B1 A1 ¡ ± ¡
+A2 A2 A2 ¢ ¢ ¢
+A3 B3 A3 £ ³ £
+A4 A4 A4 ¤ ¤ ¤
+A5 B5 A5 ¥ µ ¥
+A6 B6 A6 ¦ ¶ ¦
+A7 A7 A7 § § §
+A8 A8 A8 ¨ ¨ ¨
+A9 B9 A9 © ¹ ©
+AA BA AA ª º ª
+AB BB AB « » «
+AC BC AC ¬ ¼ ¬
+AD AD AD ­ ­ ­
+AE BE AE ® ¾ ®
+AF BF AF ¯ ¿ ¯
+B0 B0 B0 ° ° °
+B1 B1 A1 ± ± ¡
+B2 B2 B2 ² ² ²
+B3 B3 A3 ³ ³ £
+B4 B4 B4 ´ ´ ´
+B5 B5 A5 µ µ ¥
+B6 B6 A6 ¶ ¶ ¦
+B7 B7 B7 · · ·
+B8 B8 B8 ¸ ¸ ¸
+B9 B9 A9 ¹ ¹ ©
+BA BA AA º º ª
+BB BB AB » » «
+BC BC AC ¼ ¼ ¬
+BD BD BD ½ ½ ½
+BE BE AE ¾ ¾ ®
+BF BF AF ¿ ¿ ¯
+C0 E0 C0 À à À
+C1 E1 C1 Á á Á
+C2 E2 C2 Â â Â
+C3 E3 C3 Ã ã Ã
+C4 E4 C4 Ä ä Ä
+C5 E5 C5 Å å Å
+C6 E6 C6 Æ æ Æ
+C7 E7 C7 Ç ç Ç
+C8 E8 C8 È è È
+C9 E9 C9 É é É
+CA EA CA Ê ê Ê
+CB EB CB Ë ë Ë
+CC EC CC Ì ì Ì
+CD ED CD Í í Í
+CE EE CE Î î Î
+CF EF CF Ï ï Ï
+D0 F0 D0 Ð ð Ð
+D1 F1 D1 Ñ ñ Ñ
+D2 F2 D2 Ò ò Ò
+D3 F3 D3 Ó ó Ó
+D4 F4 D4 Ô ô Ô
+D5 F5 D5 Õ õ Õ
+D6 F6 D6 Ö ö Ö
+D7 D7 D7 × × ×
+D8 F8 D8 Ø ø Ø
+D9 F9 D9 Ù ù Ù
+DA FA DA Ú ú Ú
+DB FB DB Û û Û
+DC FC DC Ü ü Ü
+DD FD DD Ý ý Ý
+DE FE DE Þ þ Þ
+DF DF DF ß ß ß
+E0 E0 C0 à à À
+E1 E1 C1 á á Á
+E2 E2 C2 â â Â
+E3 E3 C3 ã ã Ã
+E4 E4 C4 ä ä Ä
+E5 E5 C5 å å Å
+E6 E6 C6 æ æ Æ
+E7 E7 C7 ç ç Ç
+E8 E8 C8 è è È
+E9 E9 C9 é é É
+EA EA CA ê ê Ê
+EB EB CB ë ë Ë
+EC EC CC ì ì Ì
+ED ED CD í í Í
+EE EE CE î î Î
+EF EF CF ï ï Ï
+F0 F0 D0 ð ð Ð
+F1 F1 D1 ñ ñ Ñ
+F2 F2 D2 ò ò Ò
+F3 F3 D3 ó ó Ó
+F4 F4 D4 ô ô Ô
+F5 F5 D5 õ õ Õ
+F6 F6 D6 ö ö Ö
+F7 F7 F7 ÷ ÷ ÷
+F8 F8 D8 ø ø Ø
+F9 F9 D9 ù ù Ù
+FA FA DA ú ú Ú
+FB FB DB û û Û
+FC FC DC ü ü Ü
+FD FD DD ý ý Ý
+FE FE DE þ þ Þ
+FF FF FF ÿ ÿ ÿ
+SELECT group_concat(a collate latin2_croatian_ci order by binary a) from t1 group by a collate latin2_croatian_ci;
+group_concat(a collate latin2_croatian_ci order by binary a)
+
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+@
+A,a,¡,±,Á,Â,Ã,Ä,á,â,ã,ä
+B,b
+C,c,Ç,ç
+È,è
+Æ,æ
+D,d,Ï,ï
+Ð,ð
+E,e,É,Ê,Ë,Ì,é,ê,ë,ì
+F,f
+G,g
+H,h
+I,i,Í,Î,í,î
+J,j
+K,k
+L,l,£,¥,³,µ,Å,å
+M,m
+N,n,Ñ,Ò,ñ,ò
+O,o,Ó,Ô,Õ,Ö,ó,ô,õ,ö
+P,p
+Q,q
+R,r,À,Ø,à,ø
+S,s,¦,ª,¶,º,ß
+©,¹
+T,t,«,»,Þ,þ
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü
+V,v
+W,w
+X,x
+Y,y,Ý,ý
+Z,z,¬,¯,¼,¿
+®,¾
+[
+\
+]
+^
+_
+`
+{
+|
+}
+~
+
+€
+
+‚
+„
+…
+†
+‡
+‰
+‹
+
+
+
+‘
+’
+“
+”
+•
+–
+—
+™
+›
+
+ÿ
+drop table t1;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 490cde82ca3..8ab24fe550b 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -817,6 +817,9 @@ drop table t1;
select 'c' like '\_' as want0;
want0
0
+SELECT SUBSTR('ваÑÑ',-2);
+SUBSTR('ваÑÑ',-2)
+ÑÑ
create table t1 (id integer, a varchar(100) character set utf8 collate utf8_unicode_ci);
insert into t1 values (1, 'Test');
select * from t1 where soundex(a) = soundex('Test');
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 177994b488d..955ea5b8673 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -462,5 +462,5 @@ rout int(11) default '0'
INSERT INTO t1 VALUES ('1',1,0);
SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
html prod
-1 0.00000
+1 0.0000
drop table t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 1cf1a19056b..0db2ceb0e6b 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -1,4 +1,9 @@
drop table if exists t1,t2;
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
+Variable_name Value
+div_precision_increment 5
create table t1 (grp int, a bigint unsigned, c char(10) not null);
insert into t1 values (1,1,"a");
insert into t1 values (2,2,"b");
@@ -44,13 +49,13 @@ count(distinct a) count(distinct grp)
6 3
select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c)
-21 6 3.5000 1.7078 2.9167 7 0 1 6 E
+21 6 3.50000 1.70783 2.91667 7 0 1 6 E
select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
NULL NULL 0 NULL NULL NULL 0 18446744073709551615 NULL NULL
-1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
-2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
-3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E
+1 1 1 1.00000 0.00000 0.00000 1 1 1 1 a a
+2 5 2 2.50000 0.50000 0.25000 3 2 2 3 b c
+3 15 3 5.00000 0.81650 0.66667 7 4 4 6 C E
select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
grp sum
NULL NULL
@@ -74,12 +79,12 @@ CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
select id, avg(value1), std(value1), variance(value1) from t1 group by id;
id avg(value1) std(value1) variance(value1)
-1 1.000000 0.816497 0.666667
-2 11.000000 0.816497 0.666667
+1 1.0000000 0.816497 0.666667
+2 11.0000000 0.816497 0.666667
select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
name avg(value1) std(value1) variance(value1)
-Set One 1.000000 0.816497 0.666667
-Set Two 11.000000 0.816497 0.666667
+Set One 1.0000000 0.816497 0.666667
+Set Two 11.0000000 0.816497 0.666667
drop table t1,t2;
create table t1 (id int not null);
create table t2 (id int not null,rating int null);
@@ -87,19 +92,19 @@ insert into t1 values(1),(2),(3);
insert into t2 values(1, 3),(2, NULL),(2, NULL),(3, 2),(3, NULL);
select t1.id, avg(rating) from t1 left join t2 on ( t1.id = t2.id ) group by t1.id;
id avg(rating)
-1 3.0000
+1 3.00000
2 NULL
-3 2.0000
+3 2.00000
select sql_small_result t2.id, avg(rating) from t2 group by t2.id;
id avg(rating)
-1 3.0000
+1 3.00000
2 NULL
-3 2.0000
+3 2.00000
select sql_big_result t2.id, avg(rating) from t2 group by t2.id;
id avg(rating)
-1 3.0000
+1 3.00000
2 NULL
-3 2.0000
+3 2.00000
select sql_small_result t2.id, avg(rating+0.0e0) from t2 group by t2.id;
id avg(rating+0.0e0)
1 3
@@ -265,22 +270,22 @@ insert into t1 values (2,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
-2 1 1 1.0000 0.0000 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
-2 1 1 1.0000 0.0000 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1
insert into t1 values (3,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
-2 1 1 1.0000 0.0000 1 1 1 1
-3 1 1 1.0000 0.0000 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1
+3 1 1 1.00000 0.00000 1 1 1 1
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) bit_xor(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 0
-2 1 1 1.0000 0.0000 1 1 1 1 1
-3 1 1 1.0000 0.0000 1 1 1 1 1
+2 1 1 1.00000 0.00000 1 1 1 1 1
+3 1 1 1.00000 0.00000 1 1 1 1 1
explain extended select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using filesort
@@ -837,10 +842,10 @@ INSERT INTO t1 VALUES (-5.00000000001),(-5.00000000002),(-5.00000000003),(-5.000
insert into t1 select * from t1;
select col1,count(col1),sum(col1),avg(col1) from t1 group by col1;
col1 count(col1) sum(col1) avg(col1)
--5.000000000030 2 -10.000000000060 -5.0000000000300000
--5.000000000020 4 -20.000000000080 -5.0000000000200000
--5.000000000010 4 -20.000000000040 -5.0000000000100000
--5.000000000000 2 -10.000000000000 -5.0000000000000000
+-5.000000000030 2 -10.000000000060 -5.00000000003000000
+-5.000000000020 4 -20.000000000080 -5.00000000002000000
+-5.000000000010 4 -20.000000000040 -5.00000000001000000
+-5.000000000000 2 -10.000000000000 -5.00000000000000000
DROP TABLE t1;
create table t1 (col1 decimal(16,12));
insert into t1 values (-5.00000000001);
@@ -947,3 +952,4 @@ SUM(a)
6
6
DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
diff --git a/mysql-test/r/func_op.result b/mysql-test/r/func_op.result
index 5f89fe7b727..61b29e9380d 100644
--- a/mysql-test/r/func_op.result
+++ b/mysql-test/r/func_op.result
@@ -1,6 +1,6 @@
select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2;
1+1 1-1 1+1*2 8/5 8%5 mod(8,5) mod(8,5)|0 -(1+1)*-2
-2 0 3 1.60000 3 3 3 4
+2 0 3 1.6000 3 3 3 4
explain extended select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index 0e558e47594..73cde35993e 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -801,5 +801,5 @@ CREATE TABLE t1 (st varchar(100));
INSERT INTO t1 VALUES ("Fake string");
CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
-ERROR HY000: Unknown error
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1, t2;
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 3b196a60d68..93216fe2003 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -461,9 +461,9 @@ Note 1003 select issimple(multipoint(point(3,6),point(4,10))) AS `issimple(Multi
create table t1 (a geometry not null);
insert into t1 values (GeomFromText('Point(1 2)'));
insert into t1 values ('Garbage');
-ERROR HY000: Unknown error
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
insert IGNORE into t1 values ('Garbage');
-ERROR HY000: Unknown error
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
alter table t1 add spatial index(a);
drop table t1;
create table t1(a geometry not null, spatial index(a));
@@ -655,3 +655,13 @@ t1 where object_id=85984;
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469)
drop table t1;
+create table t1 (fl geometry);
+insert into t1 values (1);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+insert into t1 values (1.11);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+insert into t1 values ("qwerty");
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+insert into t1 values (pointfromtext('point(1,1)'));
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+drop table t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 5cee9b15dcd..88b43c7ce35 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -440,12 +440,12 @@ create table t2 (user_id integer not null, date date);
insert into t2 values (1, '2002-06-09'),(2, '2002-06-09'),(1, '2002-06-09'),(3, '2002-06-09'),(4, '2002-06-09'),(4, '2002-06-09');
select u.gender as gender, count(distinct u.id) as dist_count, (count(distinct u.id)/5*100) as percentage from t1 u, t2 l where l.user_id = u.id group by u.gender;
gender dist_count percentage
-F 3 60.00000
-M 1 20.00000
+F 3 60.0000
+M 1 20.0000
select u.gender as gender, count(distinct u.id) as dist_count, (count(distinct u.id)/5*100) as percentage from t1 u, t2 l where l.user_id = u.id group by u.gender order by percentage;
gender dist_count percentage
-M 1 20.00000
-F 3 60.00000
+M 1 20.0000
+F 3 60.0000
drop table t1,t2;
CREATE TABLE t1 (ID1 int, ID2 int, ID int NOT NULL AUTO_INCREMENT,PRIMARY KEY(ID
));
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index 766e43b2299..3037047b513 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -1961,3 +1961,10 @@ a varchar(30), b varchar(30), primary key(a), key(b)
select distinct a from t1;
a
drop table t1;
+create table t1(a int, key(a)) engine=innodb;
+insert into t1 values(1);
+select a, count(a) from t1 group by a with rollup;
+a count(a)
+1 1
+NULL 1
+drop table t1;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index c53779582f1..0b993d681e3 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -3,10 +3,12 @@ Variable_name Value
skip_show_database OFF
grant select, update, execute on test.* to mysqltest_2@localhost;
grant select, update on test.* to mysqltest_1@localhost;
+create user mysqltest_3@localhost;
+create user mysqltest_3;
select * from information_schema.SCHEMATA where schema_name > 'm';
-CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME SQL_PATH
-NULL mysql latin1 NULL
-NULL test latin1 NULL
+CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME SQL_PATH
+NULL mysql latin1 latin1_swedish_ci NULL
+NULL test latin1 latin1_swedish_ci NULL
select schema_name from information_schema.schemata;
schema_name
information_schema
@@ -154,7 +156,9 @@ NULL mysqltest t1 a 1 NULL YES int NULL NULL 11 0 NULL NULL int(11) select,ins
show columns from mysqltest.t1 where field like "%a%";
Field Type Null Key Default Extra
a int(11) YES NULL
+create view mysqltest.v1 (c) as select a from mysqltest.t1;
grant select (a) on mysqltest.t1 to mysqltest_2@localhost;
+grant select on mysqltest.v1 to mysqltest_3;
select table_name, column_name, privileges from information_schema.columns
where table_schema = 'mysqltest' and table_name = 't1';
table_name column_name privileges
@@ -163,7 +167,11 @@ show columns from mysqltest.t1;
Field Type Null Key Default Extra
a int(11) YES NULL
b varchar(30) YES MUL NULL
-drop view v1;
+select table_name, column_name, privileges from information_schema.columns
+where table_schema = 'mysqltest' and table_name = 'v1';
+table_name column_name privileges
+v1 c select
+drop view v1, mysqltest.v1;
drop tables mysqltest.t4, mysqltest.t1, t2, t3;
drop database mysqltest;
select * from information_schema.CHARACTER_SETS
@@ -376,10 +384,10 @@ GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRAN
'mysqltest_1'@'localhost' NULL test t1 a INSERT NO
'mysqltest_1'@'localhost' NULL test t1 a UPDATE NO
'mysqltest_1'@'localhost' NULL test t1 a REFERENCES NO
-delete from mysql.user where user='mysqltest_1' or user='mysqltest_2';
-delete from mysql.db where user='mysqltest_1' or user='mysqltest_2';
-delete from mysql.tables_priv where user='mysqltest_1' or user='mysqltest_2';
-delete from mysql.columns_priv where user='mysqltest_1' or user='mysqltest_2';
+delete from mysql.user where user like 'mysqltest%';
+delete from mysql.db where user like 'mysqltest%';
+delete from mysql.tables_priv where user like 'mysqltest%';
+delete from mysql.columns_priv where user like 'mysqltest%';
flush privileges;
drop table t1;
create table t1 (a int null, primary key(a));
@@ -726,3 +734,21 @@ x_real NULL NULL
x_float NULL NULL
x_double_precision NULL NULL
drop table t1;
+create user mysqltest_4@localhost;
+SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS
+where COLUMN_NAME='TABLE_NAME';
+TABLE_NAME COLUMN_NAME PRIVILEGES
+TABLES TABLE_NAME select
+COLUMNS TABLE_NAME select
+STATISTICS TABLE_NAME select
+VIEWS TABLE_NAME select
+TABLE_PRIVILEGES TABLE_NAME select
+COLUMN_PRIVILEGES TABLE_NAME select
+TABLE_CONSTRAINTS TABLE_NAME select
+KEY_COLUMN_USAGE TABLE_NAME select
+delete from mysql.user where user='mysqltest_4';
+flush privileges;
+SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
+table_schema count(*)
+information_schema 15
+mysql 17
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
new file mode 100644
index 00000000000..0ccb22be22a
--- /dev/null
+++ b/mysql-test/r/information_schema_db.result
@@ -0,0 +1,28 @@
+use INFORMATION_SCHEMA;
+show tables;
+Tables_in_INFORMATION_SCHEMA
+SCHEMATA
+TABLES
+COLUMNS
+CHARACTER_SETS
+COLLATIONS
+COLLATION_CHARACTER_SET_APPLICABILITY
+ROUTINES
+STATISTICS
+VIEWS
+USER_PRIVILEGES
+SCHEMA_PRIVILEGES
+TABLE_PRIVILEGES
+COLUMN_PRIVILEGES
+TABLE_CONSTRAINTS
+KEY_COLUMN_USAGE
+show tables from INFORMATION_SCHEMA like 'T%';
+Tables_in_INFORMATION_SCHEMA (T%)
+TABLES
+TABLE_PRIVILEGES
+TABLE_CONSTRAINTS
+create database `inf%`;
+use `inf%`;
+show tables;
+Tables_in_inf%
+drop database `inf%`;
diff --git a/mysql-test/r/innodb-replace.result b/mysql-test/r/innodb-replace.result
index a27806640ad..b7edcc49e56 100644
--- a/mysql-test/r/innodb-replace.result
+++ b/mysql-test/r/innodb-replace.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
select * from t1;
c1 c2 stamp
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index d6cfefff9e6..b22330c7f90 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -2391,3 +2391,9 @@ drop table t1;
set storage_engine=MyISAM;
create table t1 (v varchar(16384)) engine=innodb;
drop table t1;
+create table t1(a int(1) , b int(1)) engine=innodb;
+insert into t1 values ('1111', '3333');
+select distinct concat(a, b) from t1;
+concat(a, b)
+11113333
+drop table t1;
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result
index 1817500973e..12b83640d91 100644
--- a/mysql-test/r/insert_update.result
+++ b/mysql-test/r/insert_update.result
@@ -167,3 +167,16 @@ a b c VALUES(a)
2 1 11 NULL
DROP TABLE t1;
DROP TABLE t2;
+create table t1 (a int not null unique);
+insert into t1 values (1),(2);
+insert ignore into t1 select 1 on duplicate key update a=2;
+select * from t1;
+a
+1
+2
+insert ignore into t1 select a from t1 on duplicate key update a=a+1 ;
+select * from t1;
+a
+1
+3
+drop table t1;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 6db48cff57e..2bf1155d2b5 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -943,3 +943,17 @@ Warnings:
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
drop table t1, t2;
set group_concat_max_len=default;
+create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y));
+insert t1 values (1, -5, -8, 2), (1, 2, 2, 1), (1, 1, 1, 1);
+create table t2 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, id int(11) not null, primary key (gid,id,x,y), key id (id));
+insert t2 values (1, -5, -8, 1), (1, 1, 1, 1), (1, 2, 2, 1);
+create table t3 ( set_id smallint(5) unsigned not null, id tinyint(4) unsigned not null, name char(12) not null, primary key (id,set_id));
+insert t3 values (0, 1, 'a'), (1, 1, 'b'), (0, 2, 'c'), (1, 2, 'd'), (1, 3, 'e'), (1, 4, 'f'), (1, 5, 'g'), (1, 6, 'h');
+explain select name from t1 left join t2 on t1.x = t2.x and t1.y = t2.y
+left join t3 on t1.art = t3.id where t2.id =1 and t2.x = -5 and t2.y =-8
+and t1.gid =1 and t2.gid =1 and t3.set_id =1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 10 const,const,const 1
+1 SIMPLE t2 const PRIMARY,id PRIMARY 14 const,const,const,const 1 Using index
+1 SIMPLE t3 const PRIMARY PRIMARY 3 const,const 1
+drop tables t1,t2,t3;
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index c0df8d968cb..7705961d08d 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -79,5 +79,8 @@ ERROR 42000: Not unique table/alias: 'C'
select C.a, c.a from t1 c, t2 C;
ERROR 42000: Not unique table/alias: 'C'
drop table t1, t2;
+create table t1 (a int);
+create table t2 like T1;
+drop table t1, t2;
show tables;
Tables_in_test
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index b5d5785f0f1..dcd32bf477b 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -2,7 +2,7 @@ drop table if exists t1,t2;
select 1, 1.0, -1, "hello", NULL;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def 1 8 1 1 N 32897 0 63
-def 1.0 246 4 3 N 161 1 63
+def 1.0 246 4 3 N 129 1 63
def -1 8 2 2 N 32897 0 63
def hello 253 5 5 N 1 31 8
def NULL 6 0 0 Y 32896 0 63
@@ -18,7 +18,7 @@ def test t1 t1 d d 3 11 0 Y 32768 0 63
def test t1 t1 e e 8 20 0 Y 32768 0 63
def test t1 t1 f f 4 3 0 Y 32768 2 63
def test t1 t1 g g 5 4 0 Y 32768 3 63
-def test t1 t1 h h 246 5 0 Y 0 4 63
+def test t1 t1 h h 246 7 0 Y 0 4 63
def test t1 t1 i i 13 4 0 Y 32864 0 63
def test t1 t1 j j 10 10 0 Y 128 0 63
def test t1 t1 k k 7 19 0 N 1249 0 63
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index fdbdd26b00c..6d03e8603cb 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -631,3 +631,63 @@ UNLOCK TABLES;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
DROP TABLE t1;
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (4),(5),(6);
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6);
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+DROP TABLE t1;
diff --git a/mysql-test/r/ndb_restore.result b/mysql-test/r/ndb_restore.result
index 8e4449b1996..c78a4137468 100644
--- a/mysql-test/r/ndb_restore.result
+++ b/mysql-test/r/ndb_restore.result
@@ -247,3 +247,4 @@ count(*)
3
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+520093696,1
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 06f474923eb..1d8830b7d5f 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -1,4 +1,9 @@
drop table if exists t1,t2;
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
+Variable_name Value
+div_precision_increment 5
create table t1 (product varchar(32), country_id int not null, year int, profit int);
insert into t1 values ( 'Computer', 2,2000, 1200),
( 'TV', 1, 1999, 150),
@@ -40,11 +45,11 @@ TV 600
NULL 7785
select product, sum(profit),avg(profit) from t1 group by product with rollup;
product sum(profit) avg(profit)
-Calculator 275 68.7500
-Computer 6900 1380.0000
-Phone 10 10.0000
-TV 600 120.0000
-NULL 7785 519.0000
+Calculator 275 68.75000
+Computer 6900 1380.00000
+Phone 10 10.00000
+TV 600 120.00000
+NULL 7785 519.00000
select product, country_id , year, sum(profit) from t1 group by product, country_id, year;
product country_id year sum(profit)
Calculator 1 1999 50
@@ -244,11 +249,11 @@ select product, country_id , year, sum(profit) from t1 group by product, country
product country_id year sum(profit)
select concat(':',product,':'), sum(profit),avg(profit) from t1 group by product with rollup;
concat(':',product,':') sum(profit) avg(profit)
-:Calculator: 275 68.7500
-:Computer: 6900 1380.0000
-:Phone: 10 10.0000
-:TV: 600 120.0000
-:TV: 7785 519.0000
+:Calculator: 275 68.75000
+:Computer: 6900 1380.00000
+:Phone: 10 10.00000
+:TV: 600 120.00000
+:TV: 7785 519.00000
select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
@@ -450,3 +455,4 @@ a m
2 2
NULL 3
DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index bbd95da2f82..c84c62442ef 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -570,3 +570,66 @@ id
deallocate prepare stmt|
drop procedure p1|
drop table t1|
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
+create table t1 (c1 int(11) not null, c2 int(11) not null,
+primary key (c1,c2), key c2 (c2), key c1 (c1));
+insert into t1 values (200887, 860);
+insert into t1 values (200887, 200887);
+select * from t1 where (c1=200887 and c2=200887) or c2=860;
+c1 c2
+200887 860
+200887 200887
+prepare stmt from
+"select * from t1 where (c1=200887 and c2=200887) or c2=860";
+execute stmt;
+c1 c2
+200887 860
+200887 200887
+prepare stmt from
+"select * from t1 where (c1=200887 and c2=?) or c2=?";
+set @a=200887, @b=860;
+execute stmt using @a, @b;
+c1 c2
+200887 860
+200887 200887
+deallocate prepare stmt;
+drop table t1;
+create table t1 (
+id bigint(20) not null auto_increment,
+code varchar(20) character set utf8 collate utf8_bin not null default '',
+company_name varchar(250) character set utf8 collate utf8_bin default null,
+setup_mode tinyint(4) default null,
+start_date datetime default null,
+primary key (id), unique key code (code)
+);
+create table t2 (
+id bigint(20) not null auto_increment,
+email varchar(250) character set utf8 collate utf8_bin default null,
+name varchar(250) character set utf8 collate utf8_bin default null,
+t1_id bigint(20) default null,
+password varchar(250) character set utf8 collate utf8_bin default null,
+primary_contact tinyint(4) not null default '0',
+email_opt_in tinyint(4) not null default '1',
+primary key (id), unique key email (email), key t1_id (t1_id),
+constraint t2_fk1 foreign key (t1_id) references t1 (id)
+);
+insert into t1 values
+(1, 'demo', 'demo s', 0, current_date()),
+(2, 'code2', 'name 2', 0, current_date()),
+(3, 'code3', 'name 3', 0, current_date());
+insert into t2 values
+(2, 'email1', 'name1', 3, 'password1', 0, 0),
+(3, 'email2', 'name1', 1, 'password2', 1, 0),
+(5, 'email3', 'name3', 2, 'password3', 0, 0);
+prepare stmt from 'select t2.id from t2, t1 where (t1.id=? and t2.t1_id=t1.id)';
+set @a=1;
+execute stmt using @a;
+id
+3
+select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id);
+id
+3
+deallocate prepare stmt;
+drop table t1, t2;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 37c3682cacd..d6c3d0e78d5 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -1776,8 +1776,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -1798,7 +1798,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1806,10 +1806,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -1828,7 +1828,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -1916,25 +1916,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1963,25 +1963,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2013,25 +2013,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2053,25 +2053,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2101,25 +2101,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2145,25 +2145,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2191,25 +2191,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2229,25 +2229,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index d56fcb96726..1bbc1091393 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -1759,8 +1759,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -1781,7 +1781,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1789,10 +1789,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -1811,7 +1811,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -1899,25 +1899,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1946,25 +1946,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -1996,25 +1996,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2036,25 +2036,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2084,25 +2084,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2128,25 +2128,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2174,25 +2174,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2212,25 +2212,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index 899299fa36c..009b642d7e7 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -60,8 +60,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -1760,8 +1760,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -1782,7 +1782,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1790,10 +1790,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -1812,7 +1812,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -1900,25 +1900,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1947,25 +1947,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -1997,25 +1997,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2037,25 +2037,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2085,25 +2085,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2129,25 +2129,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2175,25 +2175,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2213,25 +2213,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 4a53fe47f3f..5bd18078213 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -102,8 +102,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -1696,8 +1696,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -1718,7 +1718,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1726,10 +1726,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -1748,7 +1748,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -1836,25 +1836,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1883,25 +1883,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -1933,25 +1933,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1973,25 +1973,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2021,25 +2021,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2065,25 +2065,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2111,25 +2111,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2149,25 +2149,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -3115,8 +3115,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -4709,8 +4709,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -4731,7 +4731,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -4739,10 +4739,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -4761,7 +4761,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -4849,25 +4849,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -4896,25 +4896,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -4946,25 +4946,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -4986,25 +4986,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -5034,25 +5034,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -5078,25 +5078,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -5124,25 +5124,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -5162,25 +5162,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index 8ea5b092b5e..753def70dc0 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -1759,8 +1759,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -1781,7 +1781,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1789,10 +1789,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -1811,7 +1811,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -1899,25 +1899,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1946,25 +1946,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -1996,25 +1996,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2036,25 +2036,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2084,25 +2084,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2128,25 +2128,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2174,25 +2174,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2212,25 +2212,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index ec8c47031c1..a6da6e169db 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 7 6 Y 0 4 63
-def test t9 t9 c12 c12 246 8 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 0 4 63
+def test t9 t9 c12 c12 246 10 6 Y 0 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 1249 0 63
@@ -1759,8 +1759,8 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(3,1) NOT NULL default '0.0',
- `param02` decimal(64,30) default NULL,
+ `const02` decimal(2,1) NOT NULL default '0.0',
+ `param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
`const04` varchar(3) NOT NULL default '',
@@ -1781,7 +1781,7 @@ t5 CREATE TABLE `t5` (
`param11` bigint(20) default NULL,
`const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
- `param13` decimal(64,30) default NULL,
+ `param13` decimal(65,30) default NULL,
`param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -1789,10 +1789,10 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 1 1 63
-def test t5 t5 param02 param02 246 64 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
+def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
-def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
def test t5 t5 const05 const05 253 3 3 N 129 0 63
@@ -1811,7 +1811,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 64 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 0 30 63
def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
@@ -1899,25 +1899,25 @@ from t9 where c1= 1 ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -1946,25 +1946,25 @@ from t9 where c1= 0 ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -1996,25 +1996,25 @@ execute stmt1 using @my_key ;
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2036,25 +2036,25 @@ execute stmt1 using @my_key ;
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2084,25 +2084,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2128,25 +2128,25 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
@@ -2174,25 +2174,25 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 1 Y 128 31 63
-def @arg03 253 20 1 Y 128 31 63
-def @arg04 253 20 1 Y 128 31 63
-def @arg05 253 20 1 Y 128 31 63
-def @arg06 253 20 1 Y 128 31 63
-def @arg07 253 20 1 Y 128 31 63
-def @arg08 253 20 1 Y 128 31 63
-def @arg09 253 20 1 Y 128 31 63
-def @arg10 253 20 1 Y 128 31 63
-def @arg11 253 64 6 Y 128 30 63
-def @arg12 253 64 6 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 1 Y 128 0 63
+def @arg03 253 20 1 Y 128 0 63
+def @arg04 253 20 1 Y 128 0 63
+def @arg05 253 20 1 Y 128 0 63
+def @arg06 253 20 1 Y 128 0 63
+def @arg07 253 23 1 Y 128 31 63
+def @arg08 253 23 1 Y 128 31 63
+def @arg09 253 23 1 Y 128 31 63
+def @arg10 253 23 1 Y 128 31 63
+def @arg11 253 67 6 Y 128 30 63
+def @arg12 253 67 6 Y 128 30 63
def @arg13 253 8192 10 Y 128 31 63
def @arg14 253 8192 19 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 8 Y 128 31 63
-def @arg17 253 20 4 Y 128 31 63
-def @arg18 253 20 1 Y 128 31 63
-def @arg19 253 20 1 Y 128 31 63
+def @arg17 253 20 4 Y 128 0 63
+def @arg18 253 20 1 Y 128 0 63
+def @arg19 253 20 1 Y 128 0 63
def @arg20 253 8192 1 Y 0 31 8
def @arg21 253 8192 10 Y 0 31 8
def @arg22 253 8192 30 Y 0 31 8
@@ -2212,25 +2212,25 @@ set @my_key= 0 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 253 20 1 Y 128 31 63
-def @arg02 253 20 0 Y 128 31 63
-def @arg03 253 20 0 Y 128 31 63
-def @arg04 253 20 0 Y 128 31 63
-def @arg05 253 20 0 Y 128 31 63
-def @arg06 253 20 0 Y 128 31 63
-def @arg07 253 20 0 Y 128 31 63
-def @arg08 253 20 0 Y 128 31 63
-def @arg09 253 20 0 Y 128 31 63
-def @arg10 253 20 0 Y 128 31 63
-def @arg11 253 64 0 Y 128 30 63
-def @arg12 253 64 0 Y 128 30 63
+def @arg01 253 20 1 Y 128 0 63
+def @arg02 253 20 0 Y 128 0 63
+def @arg03 253 20 0 Y 128 0 63
+def @arg04 253 20 0 Y 128 0 63
+def @arg05 253 20 0 Y 128 0 63
+def @arg06 253 20 0 Y 128 0 63
+def @arg07 253 23 0 Y 128 31 63
+def @arg08 253 23 0 Y 128 31 63
+def @arg09 253 23 0 Y 128 31 63
+def @arg10 253 23 0 Y 128 31 63
+def @arg11 253 67 0 Y 128 30 63
+def @arg12 253 67 0 Y 128 30 63
def @arg13 253 8192 0 Y 128 31 63
def @arg14 253 8192 0 Y 128 31 63
def @arg15 253 8192 19 Y 128 31 63
def @arg16 253 8192 0 Y 128 31 63
-def @arg17 253 20 0 Y 128 31 63
-def @arg18 253 20 0 Y 128 31 63
-def @arg19 253 20 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 0 63
+def @arg18 253 20 0 Y 128 0 63
+def @arg19 253 20 0 Y 128 0 63
def @arg20 253 8192 0 Y 0 31 8
def @arg21 253 8192 0 Y 0 31 8
def @arg22 253 8192 0 Y 0 31 8
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 8db57104477..385ac1f4dfb 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -980,4 +980,31 @@ show status like 'qcache_queries_in_cache';
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
+set GLOBAL query_cache_size=64*1024;
+create table t1 (a text);
+insert into t1 values (repeat('abcdefghijklmnopqrstuvwxyz', 550));
+create table t2 (a text);
+insert into t2 values (repeat('ijklmnopqrstuvwxyzabcdefgh', 550));
+select a from t1;
+select a from t2;
+show status like 'Qcache_%_blocks';
+Variable_name Value
+Qcache_free_blocks 1
+Qcache_total_blocks 7
+insert into t1 select reverse(a) from t1;
+show status like 'Qcache_%_blocks';
+Variable_name Value
+Qcache_free_blocks 2
+Qcache_total_blocks 5
+select a from t1;
+show status like 'Qcache_%_blocks';
+Variable_name Value
+Qcache_free_blocks 1
+Qcache_total_blocks 8
+select a from t1;
+a
+abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba
+flush query cache;
+drop table t1, t2;
set GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result
new file mode 100644
index 00000000000..7b3249d553a
--- /dev/null
+++ b/mysql-test/r/rpl_sp.result
@@ -0,0 +1,258 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create database if not exists mysqltest1;
+use mysqltest1;
+create table t1 (a varchar(100));
+use mysqltest1;
+drop procedure if exists foo;
+drop procedure if exists foo2;
+drop procedure if exists foo3;
+drop procedure if exists foo4;
+drop procedure if exists bar;
+drop function if exists fn1;
+create procedure foo()
+begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end|
+ERROR HY000: This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+show binlog events from 98|
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # create database if not exists mysqltest1
+master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a varchar(100))
+create procedure foo() deterministic
+begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end|
+select * from mysql.proc where name='foo' and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL YES DEFINER begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end root@localhost # #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 foo PROCEDURE foo SQL CONTAINS_SQL YES DEFINER begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end @ # #
+set timestamp=1000000000;
+call foo();
+show binlog events from 308;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo() deterministic
+begin
+declare b int;
+set b = 8;
+insert into t1 values (b);
+insert into t1 values (unix_timestamp());
+end
+master-bin.000001 # Query 1 # use `mysqltest1`; call foo()
+select * from t1;
+a
+8
+1000000000
+select * from t1;
+a
+8
+1000000000
+delete from t1;
+create procedure foo2()
+not deterministic
+reads sql data
+select * from mysqltest1.t1;
+call foo2();
+a
+show binlog events from 605;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2()
+not deterministic
+reads sql data
+select * from mysqltest1.t1
+alter procedure foo2 contains sql;
+ERROR HY000: This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+create procedure foo3()
+deterministic
+insert into t1 values (15);
+grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
+create procedure foo4()
+deterministic
+insert into t1 values (10);
+ERROR HY000: You do not have SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
+set global log_bin_trust_routine_creators=1;
+create procedure foo4()
+deterministic
+begin
+insert into t2 values(3);
+insert into t1 values (5);
+end|
+call foo4();
+Got one of the listed errors
+show warnings;
+Level Code Message
+Warning 1417 A routine failed and is declared to modify data and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+call foo3();
+show warnings;
+Level Code Message
+call foo4();
+Got one of the listed errors
+show warnings;
+Level Code Message
+Warning 1417 A routine failed and is declared to modify data and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes
+alter procedure foo4 sql security invoker;
+call foo4();
+show warnings;
+Level Code Message
+show binlog events from 841;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
+master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int)
+master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo3()
+deterministic
+insert into t1 values (15)
+master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1
+master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1
+master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1
+master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4()
+deterministic
+begin
+insert into t2 values(3);
+insert into t1 values (5);
+end
+master-bin.000001 # Query 1 # use `mysqltest1`; call foo3()
+master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo4 sql security invoker
+master-bin.000001 # Query 1 # use `mysqltest1`; call foo4()
+select * from t1;
+a
+15
+5
+select * from t2;
+a
+3
+3
+3
+select * from t1;
+a
+15
+5
+select * from t2;
+a
+3
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES INVOKER begin
+insert into t2 values(3);
+insert into t1 values (5);
+end @ # #
+drop procedure foo4;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+drop procedure foo;
+drop procedure foo2;
+drop procedure foo3;
+create function fn1(x int)
+returns int
+deterministic
+begin
+insert into t1 values (x);
+return x+2;
+end|
+delete t1,t2 from t1,t2;
+select fn1(20);
+fn1(20)
+22
+insert into t2 values(fn1(21));
+select * from t1;
+a
+21
+20
+select * from t2;
+a
+23
+select * from t1;
+a
+21
+select * from t2;
+a
+23
+drop function fn1;
+create function fn1()
+returns int
+deterministic
+begin
+return unix_timestamp();
+end|
+delete from t1;
+set timestamp=1000000000;
+insert into t1 values(fn1());
+select * from mysql.proc where db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin
+return unix_timestamp();
+end root@localhost # #
+select * from t1;
+a
+1000000000
+use mysqltest1;
+select * from t1;
+a
+1000000000
+select * from mysql.proc where db='mysqltest1';
+db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
+mysqltest1 fn1 FUNCTION fn1 SQL CONTAINS_SQL YES DEFINER int(11) begin
+return unix_timestamp();
+end @ # #
+create trigger trg before insert on t1 for each row set new.a= 10;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+flush logs;
+delete from t1;
+create trigger trg before insert on t1 for each row set new.a= 10;
+insert into t1 values (1);
+select * from t1;
+a
+10
+select * from t1;
+a
+10
+delete from t1;
+drop trigger t1.trg;
+insert into t1 values (1);
+select * from t1;
+a
+1
+show binlog events in 'master-bin.000002' from 98;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1
+master-bin.000002 # Query 1 # use `mysqltest1`; create trigger trg before insert on t1 for each row set new.a= 10
+master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1)
+master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1
+master-bin.000002 # Query 1 # use `mysqltest1`; drop trigger t1.trg
+master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1)
+select * from t1;
+a
+1
+drop function fn1;
+drop database mysqltest1;
+drop user "zedjzlcsjhd"@127.0.0.1;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 7f131c63421..9b3c893aafa 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1672,7 +1672,7 @@ fld1 count(*)
158402 4181
select sum(Period)/count(*) from t1;
sum(Period)/count(*)
-9410.00000
+9410.0000
select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr;
companynr count sum diff func
37 12543 309394878010 0.0000 464091
@@ -1684,7 +1684,7 @@ companynr count sum diff func
512 4181 3288532102 0.0000 2140672
select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg;
companynr avg
-154 983543950.00
+154 983543950.0000
select companynr,count(*) from t2 group by companynr order by 2 desc;
companynr count(*)
37 588
@@ -2455,3 +2455,34 @@ a
select x.a, y.a, z.a from ( (t1 x inner join t2 y on x.a=y.a) inner join t2 z on y.a=z.a) WHERE x.a=1;
a a a
drop table t1,t2;
+create table t1 (s1 varchar(5));
+insert into t1 values ('Wall');
+select min(s1) from t1 group by s1 with rollup;
+min(s1)
+Wall
+Wall
+drop table t1;
+create table t1 (s1 int) engine=myisam;
+insert into t1 values (0);
+select avg(distinct s1) from t1 group by s1 with rollup;
+avg(distinct s1)
+0.0000
+0.0000
+drop table t1;
+create table t1 (s1 int);
+insert into t1 values (null),(1);
+select distinct avg(s1) as x from t1 group by s1 with rollup;
+x
+NULL
+1.0000
+drop table t1;
+create table t1 (a int(11));
+select all all * from t1;
+a
+select distinct distinct * from t1;
+a
+select all distinct * from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'distinct * from t1' at line 1
+select distinct all * from t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'all * from t1' at line 1
+drop table t1;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 9f28acbcb7d..c1164380f09 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1404,11 +1404,10 @@ show procedure status like '%p%'|
Db Name Type Definer Modified Created Security_type Comment
drop table if exists fib|
create table fib ( f bigint unsigned not null )|
-insert into fib values (1), (1)|
drop procedure if exists fib|
create procedure fib(n int unsigned)
begin
-if n > 0 then
+if n > 1 then
begin
declare x, y bigint unsigned;
declare c cursor for select f from fib order by f desc limit 2;
@@ -1421,9 +1420,20 @@ call fib(n-1);
end;
end if;
end|
+insert into fib values (0), (1)|
+call fib(3)|
+select * from fib order by f asc|
+f
+0
+1
+1
+2
+delete from fib|
+insert into fib values (0), (1)|
call fib(20)|
select * from fib order by f asc|
f
+0
1
1
2
@@ -1444,8 +1454,6 @@ f
2584
4181
6765
-10946
-17711
drop table fib|
drop procedure fib|
drop procedure if exists bar|
@@ -2913,10 +2921,10 @@ select @sptmp|
10
call bug9674_2()|
v/10
-10.00000
+10.0000
call bug9674_2()|
v/10
-10.00000
+10.0000
drop procedure bug9674_1|
drop procedure bug9674_2|
drop procedure if exists bug9598_1|
@@ -3041,4 +3049,53 @@ Warning 1265 Data truncated for column 'id' at row 2
delete from t1|
drop procedure bug9004_1|
drop procedure bug9004_2|
+drop procedure if exists bug7293|
+insert into t1 values ('secret', 0)|
+create procedure bug7293(p1 varchar(100))
+begin
+if exists (select id from t1 where soundex(p1)=soundex(id)) then
+select 'yes';
+end if;
+end;|
+call bug7293('secret')|
+yes
+yes
+call bug7293 ('secrete')|
+yes
+yes
+drop procedure bug7293|
+delete from t1|
+drop procedure if exists bug9841|
+drop view if exists v1|
+create view v1 as select * from t1, t2 where id = s|
+create procedure bug9841 ()
+update v1 set data = 10|
+call bug9841()|
+drop view v1|
+drop procedure bug9841|
+drop procedure if exists bug5963|
+create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;|
+create table t3 (s1 int)|
+insert into t3 values (5)|
+call bug5963_1()|
+v
+5
+call bug5963_1()|
+v
+5
+drop procedure bug5963_1|
+drop table t3|
+create procedure bug5963_2 (cfk_value int)
+begin
+if cfk_value in (select cpk from t3) then
+set @x = 5;
+end if;
+end;
+|
+create table t3 (cpk int)|
+insert into t3 values (1)|
+call bug5963_2(1)|
+call bug5963_2(1)|
+drop procedure bug5963_2|
+drop table t3|
drop table t1,t2;
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
index 7d1b6b67fd2..79be7a1923a 100644
--- a/mysql-test/r/strict.result
+++ b/mysql-test/r/strict.result
@@ -1232,3 +1232,8 @@ INSERT INTO t1 VALUES (DEFAULT,1);
Warnings:
Warning 1364 Field 'i' doesn't have a default value
DROP TABLE t1;
+set @@sql_mode='traditional';
+create table t1(a varchar(65537));
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead
+create table t1(a varbinary(65537));
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 40a9c3b9af5..f3f019e43ba 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -63,6 +63,9 @@ host CREATE TABLE `host` (
`Lock_tables_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Create_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Show_view_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
+ `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
PRIMARY KEY (`Host`,`Db`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'
show create table user;
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index f43fd09982a..081bd35622e 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -123,3 +123,12 @@ select * from t1;
A
This is view again
drop view t1;
+create table t1 (a int, b int, index(a), index(b));
+create table t2 (c int auto_increment, d varchar(255), primary key (c));
+insert into t1 values (3,1),(3,2);
+insert into t2 values (NULL, 'foo'), (NULL, 'bar');
+select d, c from t1 left join t2 on b = c where a = 3 order by d;
+d c
+bar 2
+foo 1
+drop table t1, t2;
diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result
index b0cd4150c9d..64c9a11b3cd 100644
--- a/mysql-test/r/type_bit.result
+++ b/mysql-test/r/type_bit.result
@@ -437,3 +437,24 @@ a+0 b+0
2303 2
12345 4
drop table t1, t2;
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+g bit(1) NOT NULL default 1, h char(1) default 'a');
+insert into t1 set a=1;
+select hex(g), h from t1;
+hex(g) h
+1 a
+drop table t1;
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+g bit(1) NOT NULL default 1);
+insert into t1 set a=1;
+select hex(g) from t1;
+hex(g)
+1
+drop table t1;
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+h char(1) default 'a') engine=myisam;
+insert into t1 set a=1;
+select h from t1;
+h
+a
+drop table t1;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 6f437ddbe0d..67a011231be 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -9,7 +9,7 @@ d mediumtext YES NULL
e longtext YES NULL
CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
Warnings:
-Note 1246 Converting column 'b' from VARCHAR to BLOB
+Note 1246 Converting column 'b' from VARBINARY to BLOB
Note 1246 Converting column 'c' from VARCHAR to TEXT
CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
Warnings:
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 920c82c3e67..98f7829ca1c 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -88,7 +88,7 @@ date numfacture expedition
0000-00-00 00:00:00 1212 0001-00-00 00:00:00
EXPLAIN SELECT * FROM t1 WHERE expedition='0001-00-00 00:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref expedition expedition 8 const 1 Using where
+1 SIMPLE t1 ref expedition expedition 8 const 1
drop table t1;
create table t1 (a datetime not null, b datetime not null);
insert into t1 values (now(), now());
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index a7b6fa1b376..ab57caacc0f 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -731,7 +731,7 @@ t1 CREATE TABLE `t1` (
`d` decimal(10,0) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
-create table t1 (d decimal(65,0));
+create table t1 (d decimal(66,0));
ERROR 42000: Incorrect column specifier for column 'd'
CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 3cdf35f5032..b0b3ab147b0 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -92,7 +92,7 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`col1` double default NULL,
- `col2` double(22,5) default NULL,
+ `col2` double(53,5) default NULL,
`col3` double default NULL,
`col4` double default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index 330caf68293..e775724ff54 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -52,13 +52,13 @@ if(1, 1.1, 1.2) if(0, 1.1, 1.2) if(0.1, 1.1, 1.2) if(0, 1, 1.1) if(0, NULL, 1.2)
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `if(1, 1.1, 1.2)` decimal(5,1) NOT NULL default '0.0',
- `if(0, 1.1, 1.2)` decimal(5,1) NOT NULL default '0.0',
- `if(0.1, 1.1, 1.2)` decimal(5,1) NOT NULL default '0.0',
- `if(0, 1, 1.1)` decimal(5,1) NOT NULL default '0.0',
- `if(0, NULL, 1.2)` decimal(5,1) default NULL,
+ `if(1, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0',
+ `if(0, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0',
+ `if(0.1, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0',
+ `if(0, 1, 1.1)` decimal(2,1) NOT NULL default '0.0',
+ `if(0, NULL, 1.2)` decimal(2,1) default NULL,
`if(1, 0.22e1, 1.1)` double NOT NULL default '0',
- `if(1E0, 1.1, 1.2)` decimal(5,1) NOT NULL default '0.0'
+ `if(1E0, 1.1, 1.2)` decimal(2,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 select nullif(1.1, 1.1), nullif(1.1, 1.2), nullif(1.1, 0.11e1), nullif(1.0, 1), nullif(1, 1.0), nullif(1, 1.1);
@@ -68,12 +68,12 @@ NULL 1.1 NULL NULL NULL 1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `nullif(1.1, 1.1)` decimal(5,1) default NULL,
- `nullif(1.1, 1.2)` decimal(5,1) default NULL,
- `nullif(1.1, 0.11e1)` double(4,1) default NULL,
- `nullif(1.0, 1)` decimal(5,1) default NULL,
- `nullif(1, 1.0)` decimal(1,0) default NULL,
- `nullif(1, 1.1)` decimal(1,0) default NULL
+ `nullif(1.1, 1.1)` decimal(2,1) default NULL,
+ `nullif(1.1, 1.2)` decimal(2,1) default NULL,
+ `nullif(1.1, 0.11e1)` decimal(2,1) default NULL,
+ `nullif(1.0, 1)` decimal(2,1) default NULL,
+ `nullif(1, 1.0)` int(1) default NULL,
+ `nullif(1, 1.1)` int(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a decimal(4,2));
@@ -174,10 +174,10 @@ create table t1 select round(15.4,-1), truncate(-5678.123451,-3), abs(-1.1), -(-
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `round(15.4,-1)` decimal(5,0) NOT NULL default '0',
- `truncate(-5678.123451,-3)` decimal(13,0) NOT NULL default '0',
- `abs(-1.1)` decimal(6,1) NOT NULL default '0.0',
- `-(-1.1)` decimal(7,1) NOT NULL default '0.0'
+ `round(15.4,-1)` decimal(3,0) NOT NULL default '0',
+ `truncate(-5678.123451,-3)` decimal(4,0) NOT NULL default '0',
+ `abs(-1.1)` decimal(3,1) NOT NULL default '0.0',
+ `-(-1.1)` decimal(2,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
set session sql_mode='traditional';
@@ -375,7 +375,7 @@ col1
drop table wl1612;
select 1/3;
1/3
-0.33333
+0.3333
select 0.8=0.7+0.1;
0.8=0.7+0.1
1
@@ -398,7 +398,7 @@ select 0.07*0.07 from wl1612_1;
0.0049
select 0.07/0.07 from wl1612_1;
0.07/0.07
-1.000000000
+1.000000
drop table wl1612_1;
create table wl1612_2 (col1 decimal(10,2), col2 numeric(10,2));
insert into wl1612_2 values(1,1);
@@ -626,16 +626,16 @@ create table wl1612_4 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
insert into wl1612_4 values(1,0.0123456789012345678912345,0.0123456789012345678912345);
select col2/9999999999 from wl1612_4 where col1=1;
col2/9999999999
-0.0000000000012345678902469135781481410000000000000000000
+0.00000000000123456789024691358
select col3/9999999999 from wl1612_4 where col1=1;
col3/9999999999
-0.0000000000012345678902469135781481410000000000000000000
+0.00000000000123456789024691358
select 9999999999/col2 from wl1612_4 where col1=1;
9999999999/col2
-810000007209.00007
+810000007209.0001
select 9999999999/col3 from wl1612_4 where col1=1;
9999999999/col3
-810000007209.00007
+810000007209.0001
select col2*9999999999 from wl1612_4 where col1=1;
col2*9999999999
123456789.0000000000111104321087655
@@ -645,16 +645,16 @@ col3*9999999999
insert into wl1612_4 values(2,55555.0123456789012345678912345,55555.0123456789012345678912345);
select col2/9999999999 from wl1612_4 where col1=2;
col2/9999999999
-0.0000055555012351234402469691331481460000000000000000000
+0.00000555550123512344024696913
select col3/9999999999 from wl1612_4 where col1=2;
col3/9999999999
-0.0000055555012351234402469691331481460000000000000000000
+0.00000555550123512344024696913
select 9999999999/col2 from wl1612_4 where col1=2;
9999999999/col2
-180001.76000
+180001.7600
select 9999999999/col3 from wl1612_4 where col1=2;
9999999999/col3
-180001.76000
+180001.7600
select col2*9999999999 from wl1612_4 where col1=2;
col2*9999999999
555550123401234.0000000000111104321087655
@@ -712,7 +712,7 @@ select .7777777777777777777777777777777777777 *
1000000000000000000;
.7777777777777777777777777777777777777 *
1000000000000000000
-777777777777777777.7777777777777777777000000000000000000
+777777777777777777.777777777777777777700000000000
select .7777777777777777777777777777777777777 - 0.1;
.7777777777777777777777777777777777777 - 0.1
0.6777777777777777777777777777777777777
@@ -772,10 +772,10 @@ round(-99999999999999999.999,3)
-99999999999999999.999
select truncate(99999999999999999999999999999999999999,31);
truncate(99999999999999999999999999999999999999,31)
-99999999999999999999999999999999999999.000000000000000000000000000
+99999999999999999999999999999999999999.000000000000000000000000000000
select truncate(99.999999999999999999999999999999999999,31);
truncate(99.999999999999999999999999999999999999,31)
-99.9999999999999999999999999999999
+100.000000000000000000000000000000
select truncate(99999999999999999999999999999999999999,-31);
truncate(99999999999999999999999999999999999999,-31)
99999990000000000000000000000000000000
@@ -783,7 +783,7 @@ create table t1 as select 0.5;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `0.5` decimal(3,1) NOT NULL default '0.0'
+ `0.5` decimal(2,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select round(1.5),round(2.5);
@@ -841,4 +841,47 @@ ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
drop table Sow6_2f;
select 10.3330000000000/12.34500000;
10.3330000000000/12.34500000
-0.8370190360469825840421223160000
+0.83701903604698258
+set sql_mode='';
+select 0/0;
+0/0
+NULL
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x;
+x
+999999999999999999999999999999999999999999999999999999999999999999999999999999999
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
+x
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select 0.190287977636363637 + 0.040372670 * 0 - 0;
+0.190287977636363637 + 0.040372670 * 0 - 0
+0.190287977636363637
+select -0.123 * 0;
+-0.123 * 0
+0.000
+CREATE TABLE t1 (f1 DECIMAL (12,9), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (10.5, 0);
+UPDATE t1 SET f1 = 4.5;
+SELECT * FROM t1;
+f1 f2
+4.500000000 0.00
+DROP TABLE t1;
+CREATE TABLE t1 (f1 DECIMAL (64,20), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0);
+SELECT * FROM t1;
+f1 f2
+9999999999999999999999999999999999.00000000000000000000 0.00
+DROP TABLE t1;
+CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB;
+INSERT INTO t1 (GRADE) VALUES (151),(252),(343);
+SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300;
+GRADE
+252
+SELECT GRADE FROM t1 WHERE GRADE= 151;
+GRADE
+151
+DROP TABLE t1;
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index 3b07464c8f4..b30e41f00d3 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -270,7 +270,7 @@ drop table t2;
create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(6) unsigned NULL NO PRI 0 #
+auto bigint(12) unsigned NULL NO PRI 0 #
t1 bigint(1) NULL NO 0 #
t2 varchar(1) latin1_swedish_ci NO #
t3 varchar(256) latin1_swedish_ci NO #
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index dcd364f1422..aae3c414c5c 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -565,7 +565,7 @@ a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` decimal(19,1) NOT NULL default '0.0'
+ `a` decimal(3,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t2 (it1 tinyint, it2 tinyint not null, i int not null, ib bigint, f float, d double, y year, da date, dt datetime, sc char(10), sv varchar(10), b blob, tx text);
@@ -792,7 +792,7 @@ d
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `d` decimal(19,9) default NULL
+ `d` decimal(18,9) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2,t3;
create table t1 select 1 union select -1;
diff --git a/mysql-test/r/user_limits.result b/mysql-test/r/user_limits.result
index 75062e97200..a94eb4616d1 100644
--- a/mysql-test/r/user_limits.result
+++ b/mysql-test/r/user_limits.result
@@ -42,11 +42,11 @@ i
select * from t1;
i
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
-ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections' resource (current value: 2)
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections_per_hour' resource (current value: 2)
select * from t1;
i
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
-ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections' resource (current value: 2)
+ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections_per_hour' resource (current value: 2)
drop user mysqltest_1@localhost;
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_user_connections 2;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 68eae111111..d9a647ce2c3 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -182,3 +182,44 @@ coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4)
set session @honk=99;
set one_shot @honk=99;
ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var= cast(NULL as signed integer);
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` bigint(20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` bigint(20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var= concat(NULL);
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @first_var=1;
+set @first_var= cast(NULL as CHAR);
+create table t1 select @first_var;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@first_var` longtext
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index b3850bcc72c..3479d209019 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -504,7 +504,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` bigint(20) default NULL,
- `c2` decimal(64,30) default NULL,
+ `c2` decimal(65,30) default NULL,
`c3` longtext,
`c4` double default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index f8629e578f0..dae106187b2 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -51,7 +51,7 @@ explain extended select c from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
Warnings:
-Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`v1`
+Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1`
create algorithm=temptable view v2 (c) as select b+1 from t1;
show create view v2;
View Create View
@@ -85,7 +85,7 @@ explain extended select c from v3;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
Warnings:
-Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`v3`
+Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1`
create algorithm=temptable view v4 (c) as select c+1 from v2;
select c from v4;
c
@@ -114,7 +114,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5
3 DERIVED t1 ALL NULL NULL NULL NULL 5
Warnings:
-Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v5`
+Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v2`
create algorithm=temptable view v6 (c) as select c+1 from v1;
select c from v6;
c
@@ -204,21 +204,6 @@ create table t1 (a int);
insert into t1 values (1), (2), (3);
create view v1 (a) as select a+1 from t1;
create view v2 (a) as select a-1 from t1;
-select * from t1 natural left join v1;
-a a
-1 NULL
-2 2
-3 3
-select * from v2 natural left join t1;
-a a
-0 NULL
-1 1
-2 2
-select * from v2 natural left join v1;
-a a
-0 NULL
-1 NULL
-2 2
drop view v1, v2;
drop table t1;
create table t1 (a int);
@@ -378,7 +363,7 @@ explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
Warnings:
-Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`v1` where (`test`.`t1`.`a` < 3)
+Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3)
update v1 set c=c+1;
select * from t1;
a b
@@ -1393,7 +1378,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`v1` left join `test`.`v2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
+Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
execute stmt1;
a a b
@@ -1712,3 +1697,18 @@ a b a b
3 3 3 3
drop view v1, v2;
drop table t1, t2, t3;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (4), (2);
+CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b;
+SELECT * FROM v1;
+a b
+2 2
+4 4
+CREATE VIEW v2 AS SELECT * FROM v1;
+SELECT * FROM v2;
+a b
+2 2
+4 4
+DROP VIEW v2,v1;
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index 9d25524da5f..51334fa62bc 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1296,6 +1296,8 @@ select fld1,fld3 from t2 where fld1 like "25050_";
create table t3 engine=archive select * from t2;
select * from t3 where fld3='bonfire';
select count(*) from t3;
+# Clean up path in error message
+--replace_result $MYSQL_TEST_DIR . /var/master-data/ /
rename table t3 to t4;
select * from t4 where fld3='bonfire';
select count(*) from t4;
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index a26b78254e7..99c8a13d0b5 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -104,3 +104,13 @@ t2.value64=t1.value64;
drop table t1, t2;
+#
+# Test of CREATE ... SELECT and unsigned integers
+#
+create table t1 select 1 as 'a';
+show create table t1;
+drop table t1;
+create table t1 select 9223372036854775809 as 'a';
+show create table t1;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index e7dd49394ee..cafecd6000d 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -4,7 +4,6 @@
select CAST(1-2 AS UNSIGNED);
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
-select CONVERT('-1',UNSIGNED);
select CAST('10 ' as unsigned integer);
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
@@ -34,6 +33,15 @@ select 10+'a';
select 10.0+cast('a' as decimal);
select 10E+0+'a';
+# out-of-range cases
+select cast('18446744073709551616' as unsigned);
+select cast('18446744073709551616' as signed);
+select cast('9223372036854775809' as signed);
+select cast('-1' as unsigned);
+select cast('abc' as signed);
+select cast('1a' as signed);
+select cast('' as signed);
+
#
# Character set convertion
#
@@ -132,6 +140,22 @@ select timediff(cast('2004-12-30 12:00:00' as time), '12:00:00');
# Still we should not throw away "days" part of time value
select timediff(cast('1 12:00:00' as time), '12:00:00');
+#
+# Bug #7036: Casting from string to unsigned would cap value of result at
+# maximum signed value instead of maximum unsigned value
+#
+select cast(18446744073709551615 as unsigned);
+select cast(18446744073709551615 as signed);
+select cast('18446744073709551615' as unsigned);
+select cast('18446744073709551615' as signed);
+select cast('9223372036854775807' as signed);
+
+select cast(concat('184467440','73709551615') as unsigned);
+select cast(concat('184467440','73709551615') as signed);
+
+select cast(repeat('1',20) as unsigned);
+select cast(repeat('1',20) as signed);
+
#decimal-related additions
select cast('1.2' as decimal(3,2));
select 1e18 * cast('1.2' as decimal(3,2));
diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test
index bc61aea2d66..c502655818d 100644
--- a/mysql-test/t/check.test
+++ b/mysql-test/t/check.test
@@ -22,3 +22,15 @@ connection con1;
reap;
drop table t1;
+#
+# Bug #9897 Views: 'Check Table' crashes MySQL, with a view and a table
+# in the statement
+#
+
+connection default;
+Create table t1(f1 int);
+Create table t2(f1 int);
+Create view v1 as Select * from t1;
+Check Table v1,t2;
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 1e2cf391221..d4733e6dc7e 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -460,3 +460,14 @@ INSERT INTO t2 VALUES ('5000000001', 'proc01', '20031029090650', '2003-10-29 13:
CREATE TABLE t3 SELECT t1.dsc,COUNT(DISTINCT t2.id) AS countOfRuns FROM t1 LEFT JOIN t2 ON (t1.id=t2.id) GROUP BY t1.id;
SELECT * FROM t3;
drop table t1, t2, t3;
+
+#
+# Bug#9666: Can't use 'DEFAULT FALSE' for column of type bool
+#
+create table t1 (b bool not null default false);
+create table t2 (b bool not null default true);
+insert into t1 values ();
+insert into t2 values ();
+select * from t1;
+select * from t2;
+drop table t1,t2;
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index e17806a54aa..88eb840a787 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -132,3 +132,11 @@ INSERT INTO t1 VALUES ('ß'),('ss'),('ss');
ALTER TABLE t1 ADD KEY ifword(col1);
SELECT * FROM t1 WHERE col1='ß' ORDER BY col1, BINARY col1;
DROP TABLE t1;
+
+#
+# Bug#9509
+#
+create table t1 (s1 char(5) character set latin1 collate latin1_german2_ci);
+insert into t1 values (0xf6) /* this is o-umlaut */;
+select * from t1 where length(s1)=1 and s1='oe';
+drop table t1;
diff --git a/mysql-test/t/ctype_latin2.test b/mysql-test/t/ctype_latin2.test
new file mode 100644
index 00000000000..cc232adeaec
--- /dev/null
+++ b/mysql-test/t/ctype_latin2.test
@@ -0,0 +1,50 @@
+
+# Tests with the latin1 character set
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET NAMES latin2;
+CREATE TABLE t1 (a char(1) character set latin2);
+INSERT INTO t1 VALUES (0x20),(0x21),(0x22),(0x23),(0x24),(0x25),(0x26),(0x27);
+INSERT INTO t1 VALUES (0x28),(0x29),(0x2A),(0x2B),(0x2C),(0x2D),(0x2E),(0x2F);
+INSERT INTO t1 VALUES (0x30),(0x31),(0x32),(0x33),(0x34),(0x35),(0x36),(0x37);
+INSERT INTO t1 VALUES (0x38),(0x39),(0x3A),(0x3B),(0x3C),(0x3D),(0x3E),(0x3F);
+INSERT INTO t1 VALUES (0x40),(0x41),(0x42),(0x43),(0x44),(0x45),(0x46),(0x47);
+INSERT INTO t1 VALUES (0x48),(0x49),(0x4A),(0x4B),(0x4C),(0x4D),(0x4E),(0x4F);
+INSERT INTO t1 VALUES (0x50),(0x51),(0x52),(0x53),(0x54),(0x55),(0x56),(0x57);
+INSERT INTO t1 VALUES (0x58),(0x59),(0x5A),(0x5B),(0x5C),(0x5D),(0x5E),(0x5F);
+INSERT INTO t1 VALUES (0x60),(0x61),(0x62),(0x63),(0x64),(0x65),(0x66),(0x67);
+INSERT INTO t1 VALUES (0x68),(0x69),(0x6A),(0x6B),(0x6C),(0x6D),(0x6E),(0x6F);
+INSERT INTO t1 VALUES (0x70),(0x71),(0x72),(0x73),(0x74),(0x75),(0x76),(0x77);
+INSERT INTO t1 VALUES (0x78),(0x79),(0x7A),(0x7B),(0x7C),(0x7D),(0x7E),(0x7F);
+INSERT INTO t1 VALUES (0x80),(0x81),(0x82),(0x83),(0x84),(0x85),(0x86),(0x87);
+INSERT INTO t1 VALUES (0x88),(0x89),(0x8A),(0x8B),(0x8C),(0x8D),(0x8E),(0x8F);
+INSERT INTO t1 VALUES (0x90),(0x91),(0x92),(0x93),(0x94),(0x95),(0x96),(0x97);
+INSERT INTO t1 VALUES (0x98),(0x99),(0x9A),(0x9B),(0x9C),(0x9D),(0x9E),(0x9F);
+INSERT INTO t1 VALUES (0xA0),(0xA1),(0xA2),(0xA3),(0xA4),(0xA5),(0xA6),(0xA7);
+INSERT INTO t1 VALUES (0xA8),(0xA9),(0xAA),(0xAB),(0xAC),(0xAD),(0xAE),(0xAF);
+INSERT INTO t1 VALUES (0xB0),(0xB1),(0xB2),(0xB3),(0xB4),(0xB5),(0xB6),(0xB7);
+INSERT INTO t1 VALUES (0xB8),(0xB9),(0xBA),(0xBB),(0xBC),(0xBD),(0xBE),(0xBF);
+INSERT INTO t1 VALUES (0xC0),(0xC1),(0xC2),(0xC3),(0xC4),(0xC5),(0xC6),(0xC7);
+INSERT INTO t1 VALUES (0xC8),(0xC9),(0xCA),(0xCB),(0xCC),(0xCD),(0xCE),(0xCF);
+INSERT INTO t1 VALUES (0xD0),(0xD1),(0xD2),(0xD3),(0xD4),(0xD5),(0xD6),(0xD7);
+INSERT INTO t1 VALUES (0xD8),(0xD9),(0xDA),(0xDB),(0xDC),(0xDD),(0xDE),(0xDF);
+INSERT INTO t1 VALUES (0xE0),(0xE1),(0xE2),(0xE3),(0xE4),(0xE5),(0xE6),(0xE7);
+INSERT INTO t1 VALUES (0xE8),(0xE9),(0xEA),(0xEB),(0xEC),(0xED),(0xEE),(0xEF);
+INSERT INTO t1 VALUES (0xF0),(0xF1),(0xF2),(0xF3),(0xF4),(0xF5),(0xF6),(0xF7);
+INSERT INTO t1 VALUES (0xF8),(0xF9),(0xFA),(0xFB),(0xFC),(0xFD),(0xFE),(0xFF);
+
+#
+# Bug#6504 upper/lower conversion bug
+#
+SELECT hex(a) ha, hex(lower(a)) hl, hex(upper(a)) hu,
+a, lower(a) l, upper(a) u from t1 order by ha;
+
+
+#
+# Bug#6505 wrong sorting order
+#
+SELECT group_concat(a collate latin2_croatian_ci order by binary a) from t1 group by a collate latin2_croatian_ci;
+drop table t1;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 194354f8718..02024adb34e 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -667,6 +667,12 @@ drop table t1;
select 'c' like '\_' as want0;
#
+# SUBSTR with negative offset didn't work with multi-byte strings
+#
+SELECT SUBSTR('ваÑÑ',-2);
+
+
+#
# Bug #7730 Server crash using soundex on an utf8 table
#
create table t1 (id integer, a varchar(100) character set utf8 collate utf8_unicode_ci);
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 9b6f91067d4..459a40cfe87 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -6,6 +6,9 @@
drop table if exists t1,t2;
--enable_warnings
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
create table t1 (grp int, a bigint unsigned, c char(10) not null);
insert into t1 values (1,1,"a");
insert into t1 values (2,2,"b");
@@ -623,4 +626,5 @@ SELECT b/c as v, SUM(a) FROM t1 GROUP BY v;
SELECT SUM(a) FROM t1 GROUP BY b/c;
DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index da59c6ae5e4..522f7a6f637 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -168,6 +168,6 @@ drop table t1;
CREATE TABLE t1 (st varchar(100));
INSERT INTO t1 VALUES ("Fake string");
CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
---error 1105
+--error 1416
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
drop table t1, t2;
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 86c34eacbc5..b7071019e9d 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -165,9 +165,9 @@ explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimpl
create table t1 (a geometry not null);
insert into t1 values (GeomFromText('Point(1 2)'));
--- error 1105
+-- error 1416
insert into t1 values ('Garbage');
--- error 1105
+-- error 1416
insert IGNORE into t1 values ('Garbage');
alter table t1 add spatial index(a);
@@ -359,3 +359,15 @@ select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85984;
drop table t1;
+
+create table t1 (fl geometry);
+--error 1416
+insert into t1 values (1);
+--error 1416
+insert into t1 values (1.11);
+--error 1416
+insert into t1 values ("qwerty");
+--error 1416
+insert into t1 values (pointfromtext('point(1,1)'));
+
+drop table t1;
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index d85b3395853..9feb4f33682 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -610,3 +610,14 @@ create table t1 (
--enable_warnings
select distinct a from t1;
drop table t1;
+
+#
+# Bug #9798: group by with rollup
+#
+
+--disable_warnings
+create table t1(a int, key(a)) engine=innodb;
+--enable_warnings
+insert into t1 values(1);
+select a, count(a) from t1 group by a with rollup;
+drop table t1;
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index b4cc118c62f..05dfeb67ccc 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -1,4 +1,4 @@
-# This test uses grants, which can't get tested for embedded server
+# This test uses grants, which can't get tested for embedded server
-- source include/not_embedded.inc
# Test for information_schema.schemata &
@@ -7,6 +7,9 @@
show variables where variable_name like "skip_show_database";
grant select, update, execute on test.* to mysqltest_2@localhost;
grant select, update on test.* to mysqltest_1@localhost;
+create user mysqltest_3@localhost;
+create user mysqltest_3;
+
select * from information_schema.SCHEMATA where schema_name > 'm';
select schema_name from information_schema.schemata;
@@ -53,15 +56,21 @@ select * from information_schema.COLUMNS where table_name="t1"
and column_name= "a";
show columns from mysqltest.t1 where field like "%a%";
+create view mysqltest.v1 (c) as select a from mysqltest.t1;
grant select (a) on mysqltest.t1 to mysqltest_2@localhost;
+grant select on mysqltest.v1 to mysqltest_3;
connect (user3,localhost,mysqltest_2,,);
connection user3;
select table_name, column_name, privileges from information_schema.columns
where table_schema = 'mysqltest' and table_name = 't1';
show columns from mysqltest.t1;
+connect (user4,localhost,mysqltest_3,,mysqltest);
+connection user4;
+select table_name, column_name, privileges from information_schema.columns
+where table_schema = 'mysqltest' and table_name = 'v1';
connection default;
-drop view v1;
+drop view v1, mysqltest.v1;
drop tables mysqltest.t4, mysqltest.t1, t2, t3;
drop database mysqltest;
@@ -176,10 +185,10 @@ select * from information_schema.USER_PRIVILEGES where grantee like '%mysqltest_
select * from information_schema.SCHEMA_PRIVILEGES where grantee like '%mysqltest_1%';
select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%';
select * from information_schema.COLUMN_PRIVILEGES where grantee like '%mysqltest_1%';
-delete from mysql.user where user='mysqltest_1' or user='mysqltest_2';
-delete from mysql.db where user='mysqltest_1' or user='mysqltest_2';
-delete from mysql.tables_priv where user='mysqltest_1' or user='mysqltest_2';
-delete from mysql.columns_priv where user='mysqltest_1' or user='mysqltest_2';
+delete from mysql.user where user like 'mysqltest%';
+delete from mysql.db where user like 'mysqltest%';
+delete from mysql.tables_priv where user like 'mysqltest%';
+delete from mysql.columns_priv where user like 'mysqltest%';
flush privileges;
drop table t1;
@@ -464,3 +473,23 @@ SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME= 't1';
drop table t1;
+
+#
+# Bug#10261 INFORMATION_SCHEMA.COLUMNS, incomplete result for non root user
+#
+
+create user mysqltest_4@localhost;
+connect (user4,localhost,mysqltest_4,,);
+connection user4;
+SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS
+where COLUMN_NAME='TABLE_NAME';
+connection default;
+delete from mysql.user where user='mysqltest_4';
+flush privileges;
+
+#
+# Bug #9404 information_schema: Weird error messages
+# with SELECT SUM() ... GROUP BY queries
+#
+SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
+
diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test
new file mode 100644
index 00000000000..f88d04c2783
--- /dev/null
+++ b/mysql-test/t/information_schema_db.test
@@ -0,0 +1,9 @@
+-- source include/testdb_only.inc
+
+use INFORMATION_SCHEMA;
+show tables;
+show tables from INFORMATION_SCHEMA like 'T%';
+create database `inf%`;
+use `inf%`;
+show tables;
+drop database `inf%`;
diff --git a/mysql-test/t/innodb-replace.test b/mysql-test/t/innodb-replace.test
index e7e96da1443..516f058a68e 100644
--- a/mysql-test/t/innodb-replace.test
+++ b/mysql-test/t/innodb-replace.test
@@ -2,6 +2,10 @@
# embedded server ignores 'delayed', so skip this
-- source include/not_embedded.inc
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
#
# Bug #1078
#
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index bd07d2220d2..335f78941da 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1300,3 +1300,12 @@ eval set storage_engine=$default;
# InnoDB specific varchar tests
create table t1 (v varchar(16384)) engine=innodb;
drop table t1;
+
+#
+# Bug #4082: integer truncation
+#
+
+create table t1(a int(1) , b int(1)) engine=innodb;
+insert into t1 values ('1111', '3333');
+select distinct concat(a, b) from t1;
+drop table t1;
diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test
index 188de8a5379..0fa366586b3 100644
--- a/mysql-test/t/insert_update.test
+++ b/mysql-test/t/insert_update.test
@@ -80,3 +80,15 @@ INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a);
SELECT *, VALUES(a) FROM t1;
DROP TABLE t1;
DROP TABLE t2;
+
+#
+# Bug#9725 - "disapearing query/hang" and "unknown error" with "on duplicate key update"
+# INSERT INGORE...UPDATE gives bad error or breaks protocol.
+#
+create table t1 (a int not null unique);
+insert into t1 values (1),(2);
+insert ignore into t1 select 1 on duplicate key update a=2;
+select * from t1;
+insert ignore into t1 select a from t1 on duplicate key update a=a+1 ;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index 25344af55b4..3a34c204905 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -661,3 +661,18 @@ select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by t1.a;
select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a;
drop table t1, t2;
set group_concat_max_len=default;
+
+#
+# BUG#10162 - ON is merged with WHERE, left join is convered to a regular join
+#
+create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y));
+insert t1 values (1, -5, -8, 2), (1, 2, 2, 1), (1, 1, 1, 1);
+create table t2 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, id int(11) not null, primary key (gid,id,x,y), key id (id));
+insert t2 values (1, -5, -8, 1), (1, 1, 1, 1), (1, 2, 2, 1);
+create table t3 ( set_id smallint(5) unsigned not null, id tinyint(4) unsigned not null, name char(12) not null, primary key (id,set_id));
+insert t3 values (0, 1, 'a'), (1, 1, 'b'), (0, 2, 'c'), (1, 2, 'd'), (1, 3, 'e'), (1, 4, 'f'), (1, 5, 'g'), (1, 6, 'h');
+explain select name from t1 left join t2 on t1.x = t2.x and t1.y = t2.y
+left join t3 on t1.art = t3.id where t2.id =1 and t2.x = -5 and t2.y =-8
+and t1.gid =1 and t2.gid =1 and t3.set_id =1;
+drop tables t1,t2,t3;
+
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index f6142b3ddfd..d60ad06b3a7 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -74,4 +74,12 @@ select * from t1 c, t2 C;
select C.a, c.a from t1 c, t2 C;
drop table t1, t2;
+#
+# Bug #9761: CREATE TABLE ... LIKE ... not handled correctly when
+# lower_case_table_names is set
+
+create table t1 (a int);
+create table t2 like T1;
+drop table t1, t2;
+
show tables;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 949c62ef288..ceae60c4577 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -204,3 +204,14 @@ CREATE TABLE t1 (a char(10));
INSERT INTO t1 VALUES ('\'');
--exec $MYSQL_DUMP --skip-comments test t1
DROP TABLE t1;
+
+#
+# Test for --insert-ignore
+#
+
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (4),(5),(6);
+--exec $MYSQL_DUMP --skip-comments --insert-ignore test t1
+--exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1
+DROP TABLE t1;
diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test
index e3191538a22..3c7b99da25a 100644
--- a/mysql-test/t/ndb_restore.test
+++ b/mysql-test/t/ndb_restore.test
@@ -209,3 +209,9 @@ select count(*)
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
--enable_warnings
+
+#
+# Test BUG#10287
+#
+
+--exec $NDB_TOOLS_DIR/ndb_select_all -d sys -D , SYSTAB_0 | grep 520093696
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index 03b26e0b6c6..378f195406b 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -2,6 +2,10 @@
drop table if exists t1,t2;
--enable_warnings
+set @sav_dpi= @@div_precision_increment;
+set div_precision_increment= 5;
+show variables like 'div_precision_increment';
+
create table t1 (product varchar(32), country_id int not null, year int, profit int);
insert into t1 values ( 'Computer', 2,2000, 1200),
( 'TV', 1, 1999, 150),
@@ -191,3 +195,4 @@ SELECT a, SUM(a) m FROM t1 GROUP BY a WITH ROLLUP;
SELECT * FROM ( SELECT a, SUM(a) m FROM t1 GROUP BY a WITH ROLLUP ) t2;
DROP TABLE t1;
+set div_precision_increment= @sav_dpi;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 820fae12db0..b06d3c4caf0 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -587,3 +587,77 @@ deallocate prepare stmt|
drop procedure p1|
drop table t1|
delimiter ;|
+
+#
+# Bug#9096 "select doesn't return all matched records if prepared statements
+# is used"
+# The bug was is bad co-operation of the optimizer's algorithm which determines
+# which keys can be used to execute a query, constants propagation
+# part of the optimizer and parameter markers used by prepared statements.
+
+drop table if exists t1;
+create table t1 (c1 int(11) not null, c2 int(11) not null,
+ primary key (c1,c2), key c2 (c2), key c1 (c1));
+
+insert into t1 values (200887, 860);
+insert into t1 values (200887, 200887);
+
+select * from t1 where (c1=200887 and c2=200887) or c2=860;
+
+prepare stmt from
+"select * from t1 where (c1=200887 and c2=200887) or c2=860";
+execute stmt;
+prepare stmt from
+"select * from t1 where (c1=200887 and c2=?) or c2=?";
+set @a=200887, @b=860;
+# this query did not return all matching rows
+execute stmt using @a, @b;
+deallocate prepare stmt;
+
+drop table t1;
+
+#
+# Bug#9777 - another occurrence of the problem stated in Bug#9096:
+# we can not compare basic constants by their names, because a placeholder
+# is a basic constant while his name is always '?'
+#
+
+create table t1 (
+ id bigint(20) not null auto_increment,
+ code varchar(20) character set utf8 collate utf8_bin not null default '',
+ company_name varchar(250) character set utf8 collate utf8_bin default null,
+ setup_mode tinyint(4) default null,
+ start_date datetime default null,
+ primary key (id), unique key code (code)
+);
+
+create table t2 (
+ id bigint(20) not null auto_increment,
+ email varchar(250) character set utf8 collate utf8_bin default null,
+ name varchar(250) character set utf8 collate utf8_bin default null,
+ t1_id bigint(20) default null,
+ password varchar(250) character set utf8 collate utf8_bin default null,
+ primary_contact tinyint(4) not null default '0',
+ email_opt_in tinyint(4) not null default '1',
+ primary key (id), unique key email (email), key t1_id (t1_id),
+ constraint t2_fk1 foreign key (t1_id) references t1 (id)
+);
+
+insert into t1 values
+(1, 'demo', 'demo s', 0, current_date()),
+(2, 'code2', 'name 2', 0, current_date()),
+(3, 'code3', 'name 3', 0, current_date());
+
+insert into t2 values
+(2, 'email1', 'name1', 3, 'password1', 0, 0),
+(3, 'email2', 'name1', 1, 'password2', 1, 0),
+(5, 'email3', 'name3', 2, 'password3', 0, 0);
+
+prepare stmt from 'select t2.id from t2, t1 where (t1.id=? and t2.t1_id=t1.id)';
+set @a=1;
+execute stmt using @a;
+
+select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id);
+
+deallocate prepare stmt;
+drop table t1, t2;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 475ba466ea9..d4e3b95e4a2 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -711,4 +711,49 @@ repair table t1;
show status like 'qcache_queries_in_cache';
drop table t1;
+# Bug #9549: Make sure cached queries that span more than one cache block
+# are handled properly in the embedded server.
+
+# We just want a small query cache, so we can fragment it easily
+set GLOBAL query_cache_size=64*1024;
+# This actually gives us a usable cache size of about 48K
+
+# Each table is about 14K
+create table t1 (a text);
+insert into t1 values (repeat('abcdefghijklmnopqrstuvwxyz', 550));
+create table t2 (a text);
+insert into t2 values (repeat('ijklmnopqrstuvwxyzabcdefgh', 550));
+
+# Load a query from each table into the query cache
+--disable_result_log
+select a from t1; # Q1
+select a from t2; # Q2
+--enable_result_log
+show status like 'Qcache_%_blocks';
+
+# Now the cache looks like (14K for Q1)(14K for Q2)(20K free)
+
+# Flush Q1 from the cache by adding an out-of-order chunk to t1
+insert into t1 select reverse(a) from t1;
+show status like 'Qcache_%_blocks';
+
+# Now the cache looks like (14K free)(14K for Q2)(20K free)
+
+# Load our new data into the query cache
+--disable_result_log
+select a from t1; # Q3
+--enable_result_log
+show status like 'Qcache_%_blocks';
+
+# Now the cache should be like (14K for Q3)(14K for Q2)(14K for Q3)(6K free)
+
+# Note that Q3 is split across two chunks!
+
+# Load Q3 from the cache, and actually pay attention to the results
+select a from t1;
+
+flush query cache;
+
+drop table t1, t2;
+
set GLOBAL query_cache_size=0;
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 84ae9674de9..5d5f845e2bc 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -1,3 +1,5 @@
+-- source include/have_innodb.inc
+
#
# Problem with range optimizer
#
@@ -435,6 +437,7 @@ explain select * from t1 where a='aaa' collate latin1_german1_ci;
drop table t1;
# Test for BUG#9348 "result for WHERE A AND (B OR C) differs from WHERE a AND (C OR B)"
+--disable_warnings
CREATE TABLE t1 (
`CLIENT` char(3) character set latin1 collate latin1_bin NOT NULL default '000',
`ARG1` char(3) character set latin1 collate latin1_bin NOT NULL default '',
@@ -443,6 +446,7 @@ CREATE TABLE t1 (
`FUNCTINT` int(11) NOT NULL default '0',
KEY `VERI_CLNT~2` (`ARG1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+--enable_warnings
INSERT INTO t1 VALUES ('000',' 0',' 0','Text 001',0), ('000',' 0',' 1','Text 002',0),
('000',' 1',' 2','Text 003',0), ('000',' 2',' 3','Text 004',0),
diff --git a/mysql-test/t/rpl_sp-master.opt b/mysql-test/t/rpl_sp-master.opt
new file mode 100644
index 00000000000..709a224fd92
--- /dev/null
+++ b/mysql-test/t/rpl_sp-master.opt
@@ -0,0 +1 @@
+--log_bin_trust_routine_creators=0
diff --git a/mysql-test/t/rpl_sp-slave.opt b/mysql-test/t/rpl_sp-slave.opt
new file mode 100644
index 00000000000..709a224fd92
--- /dev/null
+++ b/mysql-test/t/rpl_sp-slave.opt
@@ -0,0 +1 @@
+--log_bin_trust_routine_creators=0
diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test
new file mode 100644
index 00000000000..e2a8982ebaa
--- /dev/null
+++ b/mysql-test/t/rpl_sp.test
@@ -0,0 +1,266 @@
+# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
+
+source include/master-slave.inc;
+
+# First let's test replication of current_user() (that's a related thing)
+# we need a db != test, where we don't have automatic grants
+create database if not exists mysqltest1;
+use mysqltest1;
+create table t1 (a varchar(100));
+sync_slave_with_master;
+use mysqltest1;
+
+# ********************** PART 1 : STORED PROCEDURES ***************
+
+# Does the same proc as on master get inserted into mysql.proc ?
+# (same definer, same properties...)
+
+connection master;
+# cleanup
+--disable_warnings
+drop procedure if exists foo;
+drop procedure if exists foo2;
+drop procedure if exists foo3;
+drop procedure if exists foo4;
+drop procedure if exists bar;
+drop function if exists fn1;
+--enable_warnings
+
+delimiter |;
+--error 1418; # not deterministic
+create procedure foo()
+begin
+ declare b int;
+ set b = 8;
+ insert into t1 values (b);
+ insert into t1 values (unix_timestamp());
+end|
+
+--replace_column 2 # 5 #
+show binlog events from 98| # check that not there
+
+create procedure foo() deterministic
+begin
+ declare b int;
+ set b = 8;
+ insert into t1 values (b);
+ insert into t1 values (unix_timestamp());
+end|
+delimiter ;|
+
+# we replace columns having times
+# (even with fixed timestamp displayed time may changed based on TZ)
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+sync_slave_with_master;
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name='foo' and db='mysqltest1';
+
+# Now when we call it, does the CALL() get into binlog,
+# or the substatements?
+connection master;
+# see if timestamp used in SP on slave is same as on master
+set timestamp=1000000000;
+call foo();
+--replace_column 2 # 5 #
+show binlog events from 308;
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+# Now a SP which is supposed to not update tables (CALL should not be
+# binlogged) as it's "read sql data", so should not give error even if
+# non-deterministic.
+
+connection master;
+delete from t1;
+create procedure foo2()
+ not deterministic
+ reads sql data
+ select * from mysqltest1.t1;
+call foo2();
+# verify CALL is not in binlog
+--replace_column 2 # 5 #
+show binlog events from 605;
+
+--error 1418;
+alter procedure foo2 contains sql;
+
+# SP with definer's right
+
+drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+
+create procedure foo3()
+ deterministic
+ insert into t1 values (15);
+
+# let's create a non-privileged user
+grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
+grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
+
+connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,);
+connection con1;
+
+--error 1419; # only full-global-privs user can create a routine
+create procedure foo4()
+ deterministic
+ insert into t1 values (10);
+
+connection master;
+set global log_bin_trust_routine_creators=1;
+connection con1;
+
+delimiter |;
+create procedure foo4()
+ deterministic
+ begin
+ insert into t2 values(3);
+ insert into t1 values (5);
+ end|
+
+delimiter ;|
+
+# I add ,0 so that it does not print the error in the test output,
+# because this error is hostname-dependent
+--error 1142,0;
+call foo4(); # invoker has no INSERT grant on table => failure
+show warnings;
+
+connection master;
+call foo3(); # success (definer == root)
+show warnings;
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--error 1142,0;
+call foo4(); # definer's rights => failure
+show warnings;
+
+# we test replication of ALTER PROCEDURE
+alter procedure foo4 sql security invoker;
+call foo4(); # invoker's rights => success
+show warnings;
+
+# Check that only successful CALLs are in binlog
+--replace_column 2 # 5 #
+show binlog events from 841;
+
+# Note that half-failed CALLs are not in binlog, which is a known
+# bug. If we compare t2 on master and slave we see they differ:
+
+select * from t1;
+select * from t2;
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+# Test of DROP PROCEDURE
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+connection master;
+drop procedure foo4;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+sync_slave_with_master;
+select * from mysql.proc where name="foo4" and db='mysqltest1';
+
+# ********************** PART 2 : FUNCTIONS ***************
+
+connection master;
+drop procedure foo;
+drop procedure foo2;
+drop procedure foo3;
+
+delimiter |;
+create function fn1(x int)
+ returns int
+ deterministic
+begin
+ insert into t1 values (x);
+ return x+2;
+end|
+
+delimiter ;|
+delete t1,t2 from t1,t2;
+select fn1(20);
+insert into t2 values(fn1(21));
+select * from t1;
+select * from t2;
+sync_slave_with_master;
+select * from t1;
+select * from t2;
+
+connection master;
+delimiter |;
+
+drop function fn1;
+
+create function fn1()
+ returns int
+ deterministic
+begin
+ return unix_timestamp();
+end|
+delimiter ;|
+delete from t1;
+set timestamp=1000000000;
+insert into t1 values(fn1());
+
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where db='mysqltest1';
+select * from t1;
+
+sync_slave_with_master;
+use mysqltest1;
+select * from t1;
+--replace_result localhost.localdomain localhost 127.0.0.1 localhost
+--replace_column 13 # 14 #
+select * from mysql.proc where db='mysqltest1';
+
+# And now triggers
+
+connection con1;
+--error 1227;
+create trigger trg before insert on t1 for each row set new.a= 10;
+
+connection master;
+# fn1() above uses timestamps, so in !ps-protocol, the timezone will be
+# binlogged, but in --ps-protocol it will not be (BUG#9359) so
+# the binlog offsets get shifted which spoils SHOW BINLOG EVENTS.
+# To be immune, we take a new binlog.
+flush logs;
+delete from t1;
+# TODO: when triggers can contain an update, test that this update
+# does not go into binlog.
+# I'm not setting user vars in the trigger, because replication of user vars
+# would take care of propagating the user var's value to slave, so even if
+# the trigger was not executed on slave it would not be discovered.
+create trigger trg before insert on t1 for each row set new.a= 10;
+insert into t1 values (1);
+select * from t1;
+sync_slave_with_master;
+select * from t1;
+
+connection master;
+delete from t1;
+drop trigger t1.trg;
+insert into t1 values (1);
+select * from t1;
+--replace_column 2 # 5 #
+show binlog events in 'master-bin.000002' from 98;
+sync_slave_with_master;
+select * from t1;
+
+
+# Clean up
+connection master;
+drop function fn1;
+drop database mysqltest1;
+drop user "zedjzlcsjhd"@127.0.0.1;
+sync_slave_with_master;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index a92c8ffdc66..d5efeeb331e 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -2029,3 +2029,46 @@ select t1.a from (t1 inner join t2 on t1.a=t2.a) where t2.a=1;
select t1.a from ((t1 inner join t2 on t1.a=t2.a)) where t2.a=1;
select x.a, y.a, z.a from ( (t1 x inner join t2 y on x.a=y.a) inner join t2 z on y.a=z.a) WHERE x.a=1;
drop table t1,t2;
+
+#
+# Bug#9820
+#
+
+create table t1 (s1 varchar(5));
+insert into t1 values ('Wall');
+select min(s1) from t1 group by s1 with rollup;
+drop table t1;
+
+#
+# Bug#9799
+#
+
+create table t1 (s1 int) engine=myisam;
+insert into t1 values (0);
+select avg(distinct s1) from t1 group by s1 with rollup;
+drop table t1;
+
+#
+# Bug#9800
+#
+
+create table t1 (s1 int);
+insert into t1 values (null),(1);
+select distinct avg(s1) as x from t1 group by s1 with rollup;
+drop table t1;
+
+
+#
+# Bug#8733 server accepts malformed query (multiply mentioned distinct)
+#
+create table t1 (a int(11));
+select all all * from t1;
+select distinct distinct * from t1;
+--error 1064
+select all distinct * from t1;
+--error 1064
+select distinct all * from t1;
+drop table t1;
+
+
+#
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 7b3bff4eb55..80acaacfdb3 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1634,8 +1634,6 @@ drop table if exists fib|
--enable_warnings
create table fib ( f bigint unsigned not null )|
-insert into fib values (1), (1)|
-
# We deliberately do it the awkward way, fetching the last two
# values from the table, in order to exercise various statements
# and table accesses at each turn.
@@ -1644,7 +1642,7 @@ drop procedure if exists fib|
--enable_warnings
create procedure fib(n int unsigned)
begin
- if n > 0 then
+ if n > 1 then
begin
declare x, y bigint unsigned;
declare c cursor for select f from fib order by f desc limit 2;
@@ -1659,6 +1657,20 @@ begin
end if;
end|
+# Minimum test: recursion of 3 levels
+
+insert into fib values (0), (1)|
+
+call fib(3)|
+
+select * from fib order by f asc|
+
+delete from fib|
+
+# Original test: 20 levels (may run into memory limits!)
+
+insert into fib values (0), (1)|
+
call fib(20)|
select * from fib order by f asc|
@@ -3723,6 +3735,71 @@ delete from t1|
drop procedure bug9004_1|
drop procedure bug9004_2|
+#
+# BUG#7293: Stored procedure crash with soundex
+#
+--disable_warnings
+drop procedure if exists bug7293|
+--enable_warnings
+insert into t1 values ('secret', 0)|
+create procedure bug7293(p1 varchar(100))
+begin
+ if exists (select id from t1 where soundex(p1)=soundex(id)) then
+ select 'yes';
+ end if;
+end;|
+call bug7293('secret')|
+call bug7293 ('secrete')|
+drop procedure bug7293|
+delete from t1|
+
+
+#
+# BUG#9841: Unexpected read lock when trying to update a view in a
+# stored procedure
+#
+--disable_warnings
+drop procedure if exists bug9841|
+drop view if exists v1|
+--enable_warnings
+
+create view v1 as select * from t1, t2 where id = s|
+create procedure bug9841 ()
+ update v1 set data = 10|
+call bug9841()|
+
+drop view v1|
+drop procedure bug9841|
+
+
+#
+# BUG#5963 subqueries in SET/IF
+#
+--disable_warnings
+drop procedure if exists bug5963|
+--enable_warnings
+
+create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;|
+create table t3 (s1 int)|
+insert into t3 values (5)|
+call bug5963_1()|
+call bug5963_1()|
+drop procedure bug5963_1|
+drop table t3|
+
+create procedure bug5963_2 (cfk_value int)
+begin
+ if cfk_value in (select cpk from t3) then
+ set @x = 5;
+ end if;
+ end;
+|
+create table t3 (cpk int)|
+insert into t3 values (1)|
+call bug5963_2(1)|
+call bug5963_2(1)|
+drop procedure bug5963_2|
+drop table t3|
#
# BUG#NNNN: New bug synopsis
diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test
index 333ec40b1b9..298653b554a 100644
--- a/mysql-test/t/strict.test
+++ b/mysql-test/t/strict.test
@@ -1083,3 +1083,13 @@ INSERT INTO t1 SET j = 1, i = DEFAULT;
INSERT INTO t1 SET j = 1, i = DEFAULT(i);
INSERT INTO t1 VALUES (DEFAULT,1);
DROP TABLE t1;
+
+#
+# Bugs #8295 and #8296: varchar and varbinary conversion
+#
+
+set @@sql_mode='traditional';
+--error 1074
+create table t1(a varchar(65537));
+--error 1074
+create table t1(a varbinary(65537));
diff --git a/mysql-test/t/temp_table-master.opt b/mysql-test/t/temp_table-master.opt
new file mode 100644
index 00000000000..026d3d4640c
--- /dev/null
+++ b/mysql-test/t/temp_table-master.opt
@@ -0,0 +1 @@
+--tmpdir=$MYSQL_TEST_DIR/var//tmp
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index eeb33515570..da7ce9b4722 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -104,3 +104,11 @@ drop table t1;
select * from t1;
drop view t1;
+# Bug #8497: tmpdir with extra slashes would cause failures
+#
+create table t1 (a int, b int, index(a), index(b));
+create table t2 (c int auto_increment, d varchar(255), primary key (c));
+insert into t1 values (3,1),(3,2);
+insert into t2 values (NULL, 'foo'), (NULL, 'bar');
+select d, c from t1 left join t2 on b = c where a = 3 order by d;
+drop table t1, t2;
diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test
index 1fbcf01d5a6..19d16f95990 100644
--- a/mysql-test/t/type_bit.test
+++ b/mysql-test/t/type_bit.test
@@ -140,3 +140,25 @@ drop table t1;
create table t1 select * from t2;
select a+0, b+0 from t1;
drop table t1, t2;
+
+#
+# Bug #10179: problem with NULLs and default values
+#
+
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+ g bit(1) NOT NULL default 1, h char(1) default 'a');
+insert into t1 set a=1;
+select hex(g), h from t1;
+drop table t1;
+
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+ g bit(1) NOT NULL default 1);
+insert into t1 set a=1;
+select hex(g) from t1;
+drop table t1;
+
+create table t1 (a int, b time, c tinyint, d bool, e char(10), f bit(1),
+ h char(1) default 'a') engine=myisam;
+insert into t1 set a=1;
+select h from t1;
+drop table t1;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index f86113ac66b..7ce54847506 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -308,7 +308,7 @@ create table t1 (d decimal);
show create table t1;
drop table t1;
--error 1063
-create table t1 (d decimal(65,0));
+create table t1 (d decimal(66,0));
#
# Test example from manual
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index e85cc3d55c6..78ad5ed2286 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -869,3 +869,50 @@ drop table Sow6_2f;
# bug#9501
#
select 10.3330000000000/12.34500000;
+
+#
+# Bug #10404
+#
+
+set sql_mode='';
+select 0/0;
+
+#
+# bug #9546
+#
+--disable_ps_protocol
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 as x;
+select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
+--enable_ps_protocol
+#
+# Bug #10004
+#
+select 0.190287977636363637 + 0.040372670 * 0 - 0;
+#
+# Bug #9527
+#
+select -0.123 * 0;
+
+#
+# Bug #10232
+#
+
+CREATE TABLE t1 (f1 DECIMAL (12,9), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (10.5, 0);
+UPDATE t1 SET f1 = 4.5;
+SELECT * FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (f1 DECIMAL (64,20), f2 DECIMAL(2,2));
+INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug #10465
+#
+
+CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB;
+INSERT INTO t1 (GRADE) VALUES (151),(252),(343);
+SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300;
+SELECT GRADE FROM t1 WHERE GRADE= 151;
+DROP TABLE t1;
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index ef360f2231d..b9d06558f34 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -119,3 +119,29 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4);
set session @honk=99;
--error 1382
set one_shot @honk=99;
+
+#
+# Bug #6598: problem with cast(NULL as signed integer);
+#
+
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var= cast(NULL as signed integer);
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var= NULL;
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var= concat(NULL);
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
+set @first_var=1;
+set @first_var= cast(NULL as CHAR);
+create table t1 select @first_var;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 0303605a9ef..42223dfa82e 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -148,9 +148,10 @@ insert into t1 values (1), (2), (3);
create view v1 (a) as select a+1 from t1;
create view v2 (a) as select a-1 from t1;
-select * from t1 natural left join v1;
-select * from v2 natural left join t1;
-select * from v2 natural left join v1;
+# WL #2486 should enable these tests
+#select * from t1 natural left join v1;
+#select * from v2 natural left join t1;
+#select * from v2 natural left join v1;
drop view v1, v2;
drop table t1;
@@ -1533,3 +1534,18 @@ select * from v2 A, v2 B where A.a = B.b;
drop view v1, v2;
drop table t1, t2, t3;
+#
+# Test case for bug #8528: select from view over multi-table view
+#
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4);
+INSERT INTO t2 VALUES (4), (2);
+
+CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b;
+SELECT * FROM v1;
+CREATE VIEW v2 AS SELECT * FROM v1;
+SELECT * FROM v2;
+
+DROP VIEW v2,v1;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index d8a13ca9dfd..26f3477140b 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -25,6 +25,24 @@
}
{
+ pthread allocate_dtv memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls
+ fun:pthread_create*
+}
+
+{
+ pthread allocate_dtv memory loss second
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls
+ fun:pthread_create*
+}
+
+{
pthread memalign memory loss
Memcheck:Leak
fun:memalign
@@ -34,6 +52,28 @@
}
{
+ pthread strstr uninit
+ Memcheck:Cond
+ fun:strstr
+ obj:/lib/tls/libpthread.so.*
+ obj:/lib/tls/libpthread.so.*
+ fun:call_init
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
+ pthread strstr uninit
+ Memcheck:Cond
+ fun:strstr
+ obj:/lib/tls/libpthread.so.*
+ obj:/lib/tls/libpthread.so.*
+ fun:call_init
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
pthread errno
Memcheck:Leak
fun:calloc
diff --git a/mysys/default.c b/mysys/default.c
index 0f33c94d17e..d35eb399b80 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -45,11 +45,12 @@ char *defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
-#define MAX_DEFAULT_DIRS 4
+#define MAX_DEFAULT_DIRS 5
const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
+static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
#endif
@@ -107,19 +108,21 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
uint *args_used, Process_option_func func,
void *func_ctx)
{
- const char **dirs, *forced_default_file;
+ const char **dirs, *forced_default_file, *forced_extra_defaults;
int error= 0;
DBUG_ENTER("my_search_option_files");
/* Check if we want to force the use a specific default file */
get_defaults_files(*argc, *argv,
- (char **)&forced_default_file, &defaults_extra_file);
+ (char **)&forced_default_file,
+ (char **)&forced_extra_defaults);
if (forced_default_file)
forced_default_file= strchr(forced_default_file,'=')+1;
- if (defaults_extra_file)
- defaults_extra_file= strchr(defaults_extra_file,'=')+1;
+ if (forced_extra_defaults)
+ defaults_extra_file= strchr(forced_extra_defaults,'=')+1;
- (*args_used)+= (forced_default_file ? 1 : 0) + (defaults_extra_file ? 1 : 0);
+ (*args_used)+= (forced_default_file ? 1 : 0) +
+ (forced_extra_defaults ? 1 : 0);
if (forced_default_file)
{
@@ -140,20 +143,6 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
}
else
{
-#ifdef __WIN__
- char system_dir[FN_REFLEN];
- GetWindowsDirectory(system_dir,sizeof(system_dir));
- if ((search_default_file(func, func_ctx, system_dir, conf_file)))
- goto err;
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
- if ((etc= getenv("ETC")) &&
- (search_default_file(func, func_ctx, etc, conf_file)) < 0)
- goto err;
- }
-#endif
for (dirs= default_directories ; *dirs; dirs++)
{
if (**dirs)
@@ -163,10 +152,15 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
}
else if (defaults_extra_file)
{
- if (search_default_file(func, func_ctx, NullS,
- defaults_extra_file) < 0)
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ defaults_extra_file, 0)) < 0)
goto err; /* Fatal error */
-
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ defaults_extra_file);
+ goto err;
+ }
}
}
}
@@ -396,8 +390,11 @@ static int search_default_file(Process_option_func opt_handler,
const char *config_file)
{
char **ext;
+ const char *empty_list[]= { "", 0 };
+ my_bool have_ext= fn_ext(config_file)[0] != 0;
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; *ext++)
{
int error;
if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
@@ -410,6 +407,56 @@ static int search_default_file(Process_option_func opt_handler,
/*
+ Skip over keyword and get argument after keyword
+
+ SYNOPSIS
+ get_argument()
+ keyword Include directive keyword
+ kwlen Length of keyword
+ ptr Pointer to the keword in the line under process
+ line line number
+
+ RETURN
+ 0 error
+ # Returns pointer to the argument after the keyword.
+*/
+
+static char *get_argument(const char *keyword, uint kwlen,
+ char *ptr, char *name, uint line)
+{
+ char *end;
+
+ /* Skip over "include / includedir keyword" and following whitespace */
+
+ for (ptr+= kwlen - 1;
+ my_isspace(&my_charset_latin1, ptr[0]);
+ ptr++)
+ {}
+
+ /*
+ Trim trailing whitespace from directory name
+ The -1 below is for the newline added by fgets()
+ Note that my_isspace() is true for \r and \n
+ */
+ for (end= ptr + strlen(ptr) - 1;
+ my_isspace(&my_charset_latin1, *(end - 1));
+ end--)
+ {}
+ end[0]= 0; /* Cut off end space */
+
+ /* Print error msg if there is nothing after !include* directive */
+ if (end <= ptr)
+ {
+ fprintf(stderr,
+ "error: Wrong '!%s' directive in config file: %s at line %d\n",
+ keyword, name, line);
+ return 0;
+ }
+ return ptr;
+}
+
+
+/*
Open a configuration file (if exists) and read given options from it
SYNOPSIS
@@ -484,7 +531,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
}
#endif
if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
- return 0; /* Ignore wrong files */
+ return 1; /* Ignore wrong files */
while (fgets(buff, sizeof(buff) - 1, fp))
{
@@ -497,40 +544,34 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
continue;
/* Configuration File Directives */
- if ((*ptr == '!') && (recursion_level < max_recursion_level))
+ if ((*ptr == '!'))
{
+ if (recursion_level >= max_recursion_level)
+ {
+ for (end= ptr + strlen(ptr) - 1;
+ my_isspace(&my_charset_latin1, *(end - 1));
+ end--)
+ {}
+ end[0]= 0;
+ fprintf(stderr,
+ "Warning: skipping '%s' directive as maximum include"
+ "recursion level was reached in file %s at line %d\n",
+ ptr, name, line);
+ continue;
+ }
+
/* skip over `!' and following whitespace */
for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++)
{}
- if ((!strncmp(ptr, includedir_keyword, sizeof(includedir_keyword) - 1))
- && my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
+ if ((!strncmp(ptr, includedir_keyword,
+ sizeof(includedir_keyword) - 1)) &&
+ my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
{
- /* skip over "includedir" and following whitespace */
- for (ptr+= sizeof(includedir_keyword) - 1;
- my_isspace(&my_charset_latin1, ptr[0]); ptr++)
- {}
-
- /* trim trailing whitespace from directory name */
- end= ptr + strlen(ptr) - 1;
- /* fgets() stores the newline character in the buffer */
- if ((end[0] == '\n') || (end[0] == '\r') ||
- my_isspace(&my_charset_latin1, end[0]))
- {
- for (; my_isspace(&my_charset_latin1, *(end - 1)); end--)
- {}
- end[0]= 0;
- }
-
- /* print error msg if there is nothing after !includedir directive */
- if (end == ptr)
- {
- fprintf(stderr,
- "error: Wrong !includedir directive in config "
- "file: %s at line %d\n",
- name,line);
- goto err;
- }
+ if (!(ptr= get_argument(includedir_keyword,
+ sizeof(includedir_keyword),
+ ptr, name, line)))
+ goto err;
if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
goto err;
@@ -559,28 +600,13 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
my_dirend(search_dir);
}
- else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1))
- && my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword) - 1]))
+ else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
+ my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
{
- /* skip over `include' and following whitespace */
- for (ptr+= sizeof(include_keyword) - 1;
- my_isspace(&my_charset_latin1, ptr[0]); ptr++)
- {}
-
- /* trim trailing whitespace from filename */
- end= ptr + strlen(ptr) - 1;
- for (; my_isspace(&my_charset_latin1, *(end - 1)) ; end--)
- {}
- end[0]= 0;
-
- if (end == ptr)
- {
- fprintf(stderr,
- "error: Wrong !include directive in config "
- "file: %s at line %d\n",
- name,line);
- goto err;
- }
+ if (!(ptr= get_argument(include_keyword,
+ sizeof(include_keyword), ptr,
+ name, line)))
+ goto err;
search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
recursion_level + 1);
@@ -588,14 +614,6 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
continue;
}
- else
- if (recursion_level >= max_recursion_level)
- {
- fprintf(stderr,
- "warning: skipping !include directive as maximum include"
- "recursion level was reached in file %s at line %d\n",
- name, line);
- }
if (*ptr == '[') /* Group name */
{
@@ -734,11 +752,11 @@ static char *remove_end_comment(char *ptr)
#include <help_start.h>
-void print_defaults(const char *conf_file, const char **groups)
+void my_print_default_files(const char *conf_file)
{
-#ifdef __WIN__
+ const char *empty_list[]= { "", 0 };
my_bool have_ext= fn_ext(conf_file)[0] != 0;
-#endif
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
char name[FN_REFLEN], **ext;
const char **dirs;
@@ -749,30 +767,9 @@ void print_defaults(const char *conf_file, const char **groups)
fputs(conf_file,stdout);
else
{
-#ifdef __WIN__
- GetWindowsDirectory(name,sizeof(name));
- if (!have_ext)
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", name, conf_file, *ext);
- }
- else
- printf("%s\\%s ", name, conf_file);
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
-
- if ((etc= getenv("ETC")))
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", etc, conf_file, *ext);
- }
- }
-#endif
for (dirs=default_directories ; *dirs; dirs++)
{
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; *ext++)
{
const char *pos;
char *end;
@@ -791,6 +788,12 @@ void print_defaults(const char *conf_file, const char **groups)
}
puts("");
}
+}
+
+void print_defaults(const char *conf_file, const char **groups)
+{
+ my_print_default_files(conf_file);
+
fputs("The following groups are read:",stdout);
for ( ; *groups ; groups++)
{
@@ -806,15 +809,58 @@ void print_defaults(const char *conf_file, const char **groups)
#include <help_end.h>
+
+/*
+ Create the list of default directories.
+
+ On Microsoft Windows, this is:
+ 1. C:/
+ 2. GetWindowsDirectory()
+ 3. GetSystemWindowsDirectory()
+ 4. getenv(DEFAULT_HOME_ENV)
+ 5. ""
+
+ On Novell NetWare, this is:
+ 1. sys:/etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+
+ On OS/2, this is:
+ 1. getenv(ETC)
+ 2. /etc/
+ 3. getenv(DEFAULT_HOME_ENV)
+ 4. ""
+ 5. "~/"
+
+ Everywhere else, this is:
+ 1. /etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+ 4. "~/"
+
+ */
+
static void init_default_directories()
{
const char *env, **ptr= default_directories;
#ifdef __WIN__
*ptr++= "C:/";
+
+ if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
+ *ptr++= &system_dir;
+ /* Only add shared system directory if different from default. */
+ if (GetSystemWindowsDirectory(shared_system_dir,sizeof(shared_system_dir)) &&
+ strcmp(system_dir, shared_system_dir))
+ *ptr++= &shared_system_dir;
+
#elif defined(__NETWARE__)
*ptr++= "sys:/etc/";
#else
+#if defined(__EMX__) || defined(OS2)
+ if ((env= getenv("ETC")))
+ *ptr++= env;
+#endif
*ptr++= "/etc/";
#endif
if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 4967b60cd68..2308536cd37 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -1025,8 +1025,8 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
for a too long time (this time is determined by parameter age_threshold).
*/
-static inline void unreg_request(KEY_CACHE *keycache,
- BLOCK_LINK *block, int at_end)
+static void unreg_request(KEY_CACHE *keycache,
+ BLOCK_LINK *block, int at_end)
{
if (! --block->requests)
{
@@ -1045,10 +1045,13 @@ static inline void unreg_request(KEY_CACHE *keycache,
}
link_block(keycache, block, hot, (my_bool)at_end);
block->last_hit_time= keycache->keycache_time;
- if (++keycache->keycache_time - keycache->used_ins->last_hit_time >
+ keycache->keycache_time++;
+
+ block= keycache->used_ins;
+ /* Check if we should link a hot block to the warm block */
+ if (block && keycache->keycache_time - block->last_hit_time >
keycache->age_threshold)
{
- block= keycache->used_ins;
unlink_block(keycache, block);
link_block(keycache, block, 0, 0);
if (block->temperature != BLOCK_WARM)
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index d6f647254e8..89f949eca27 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -192,3 +192,25 @@ int test_if_hard_path(register const char *dir_name)
return FALSE;
#endif
} /* test_if_hard_path */
+
+
+/*
+ Test if a name contains an (absolute or relative) path.
+
+ SYNOPSIS
+ has_path()
+ name The name to test.
+
+ RETURN
+ TRUE name contains a path.
+ FALSE name does not contain a path.
+*/
+
+my_bool has_path(const char *name)
+{
+ return test(strchr(name, FN_LIBCHAR))
+#ifdef FN_DEVCHAR
+ || test(strchr(name, FN_DEVCHAR))
+#endif
+ ;
+}
diff --git a/mysys/my_new.cc b/mysys/my_new.cc
index 14423c3afd5..66f3a14eeb4 100644
--- a/mysys/my_new.cc
+++ b/mysys/my_new.cc
@@ -45,5 +45,14 @@ void operator delete[] (void *ptr) throw ()
free(ptr);
}
+C_MODE_START
+
+int __cxa_pure_virtual() {
+ assert("Pure virtual method called." == "Aborted");
+ return 0;
+}
+
+C_MODE_END
+
#endif /* USE_MYSYS_NEW */
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 878e1f6bfc6..4d23d01cd82 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -67,12 +67,11 @@ my_bool my_thread_global_init(void)
/*
Set mutex type to "fast" a.k.a "adaptive"
- The mutex kind determines what happens if a thread attempts to lock
- a mutex it already owns with pthread_mutex_lock(3). If the mutex
- is of the ``fast'' kind, pthread_mutex_lock(3) simply suspends
- the calling thread forever. If the mutex is of the ``error checking''
- kind, pthread_mutex_lock(3) returns immediately with the error
- code EDEADLK.
+ In this case the thread may steal the mutex from some other thread
+ that is waiting for the same mutex. This will save us some
+ context switches but may cause a thread to 'starve forever' while
+ waiting for the mutex (not likely if the code within the mutex is
+ short).
*/
pthread_mutexattr_init(&my_fast_mutexattr);
pthread_mutexattr_settype(&my_fast_mutexattr,
diff --git a/ndb/src/common/portlib/gcc.cpp b/ndb/src/common/portlib/gcc.cpp
index 66aa4812dc6..4e49d787d3c 100644
--- a/ndb/src/common/portlib/gcc.cpp
+++ b/ndb/src/common/portlib/gcc.cpp
@@ -2,6 +2,6 @@
/**
* GCC linking problem...
*/
-#ifdef DEFINE_CXA_PURE_VIRTUAL
+#if 0
extern "C" { int __cxa_pure_virtual() { return 0;} }
#endif
diff --git a/ndb/src/common/util/new.cpp b/ndb/src/common/util/new.cpp
index 901f74bf979..643800f1582 100644
--- a/ndb/src/common/util/new.cpp
+++ b/ndb/src/common/util/new.cpp
@@ -6,7 +6,7 @@ extern "C" {
void (* ndb_new_handler)() = 0;
}
-#ifdef USE_MYSYS_NEW
+#if 0
void *operator new (size_t sz)
{
diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp
index 63d0aaafe86..b009f0c0fc4 100644
--- a/ndb/src/cw/cpcd/APIService.cpp
+++ b/ndb/src/cw/cpcd/APIService.cpp
@@ -122,6 +122,7 @@ ParserRow<CPCDAPISession> commands[] =
CPCD_ARG("stderr", String, Optional, "Redirection of stderr"),
CPCD_ARG("stdin", String, Optional, "Redirection of stderr"),
CPCD_ARG("ulimit", String, Optional, "ulimit"),
+ CPCD_ARG("shutdown", String, Optional, "shutdown options"),
CPCD_CMD("undefine process", &CPCDAPISession::undefineProcess, ""),
CPCD_CMD_ALIAS("undef", "undefine process", 0),
diff --git a/ndb/src/cw/cpcd/CPCD.hpp b/ndb/src/cw/cpcd/CPCD.hpp
index a5c0bef1dac..aecc43150c4 100644
--- a/ndb/src/cw/cpcd/CPCD.hpp
+++ b/ndb/src/cw/cpcd/CPCD.hpp
@@ -243,6 +243,12 @@ public:
* @desc Format c:unlimited d:0 ...
*/
BaseString m_ulimit;
+
+ /**
+ * @brief shutdown options
+ */
+ BaseString m_shutdown_options;
+
private:
class CPCD *m_cpcd;
void do_exec();
diff --git a/ndb/src/cw/cpcd/Process.cpp b/ndb/src/cw/cpcd/Process.cpp
index 2509f34e882..cfffec7d0ce 100644
--- a/ndb/src/cw/cpcd/Process.cpp
+++ b/ndb/src/cw/cpcd/Process.cpp
@@ -44,6 +44,8 @@ CPCD::Process::print(FILE * f){
fprintf(f, "stdout: %s\n", m_stdout.c_str() ? m_stdout.c_str() : "");
fprintf(f, "stderr: %s\n", m_stderr.c_str() ? m_stderr.c_str() : "");
fprintf(f, "ulimit: %s\n", m_ulimit.c_str() ? m_ulimit.c_str() : "");
+ fprintf(f, "shutdown: %s\n", m_shutdown_options.c_str() ?
+ m_shutdown_options.c_str() : "");
}
CPCD::Process::Process(const Properties & props, class CPCD *cpcd) {
@@ -64,6 +66,7 @@ CPCD::Process::Process(const Properties & props, class CPCD *cpcd) {
props.get("stdout", m_stdout);
props.get("stderr", m_stderr);
props.get("ulimit", m_ulimit);
+ props.get("shutdown", m_shutdown_options);
m_status = STOPPED;
if(strcasecmp(m_type.c_str(), "temporary") == 0){
@@ -220,8 +223,11 @@ set_ulimit(const BaseString & pair){
if(!(list[1].trim() == "unlimited")){
value = atoi(list[1].c_str());
}
-
+#if defined(__INTEL_COMPILER)
+ struct rlimit64 rlp;
+#else
struct rlimit rlp;
+#endif
#define _RLIMIT_FIX(x) { res = getrlimit(x,&rlp); if(!res){ rlp.rlim_cur = value; res = setrlimit(x, &rlp); }}
if(list[0].trim() == "c"){
@@ -451,7 +457,11 @@ CPCD::Process::stop() {
m_status = STOPPING;
errno = 0;
- int ret = kill(-m_pid, SIGTERM);
+ int signo= SIGTERM;
+ if(m_shutdown_options == "SIGKILL")
+ signo= SIGKILL;
+
+ int ret = kill(-m_pid, signo);
switch(ret) {
case 0:
logger.debug("Sent SIGTERM to pid %d", (int)-m_pid);
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 3d5340494ab..b9877dae46c 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -4061,12 +4061,14 @@ calcLHbits(Uint32 * lhPageBits, Uint32 * lhDistrBits,
tmp <<= 1;
distrBits++;
}//while
+#ifdef ndb_classical_lhdistrbits
if (tmp != totalFragments) {
tmp >>= 1;
if ((fid >= (totalFragments - tmp)) && (fid < (tmp - 1))) {
distrBits--;
}//if
}//if
+#endif
* lhPageBits = pageBits;
* lhDistrBits = distrBits;
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index 2baa4400409..2983b02de67 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -585,34 +585,8 @@ public:
*/
ArrayPool<TcIndexOperation> c_theIndexOperationPool;
- /**
- * The list of index operations
- */
- ArrayList<TcIndexOperation> c_theIndexOperations;
-
UintR c_maxNumberOfIndexOperations;
- struct TcSeizedIndexOperation {
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- /**
- * Prev pointer (used in list)
- */
- Uint32 prevList;
- };
-
- /**
- * Pool of seized index operations
- */
- ArrayPool<TcSeizedIndexOperation> c_theSeizedIndexOperationPool;
-
- typedef Ptr<TcSeizedIndexOperation> TcSeizedIndexOperationPtr;
-
/************************** API CONNECT RECORD ***********************
* The API connect record contains the connection record to which the
* application connects.
@@ -650,7 +624,7 @@ public:
struct ApiConnectRecord {
ApiConnectRecord(ArrayPool<TcFiredTriggerData> & firedTriggerPool,
- ArrayPool<TcSeizedIndexOperation> & seizedIndexOpPool):
+ ArrayPool<TcIndexOperation> & seizedIndexOpPool):
theFiredTriggers(firedTriggerPool),
isIndexOp(false),
theSeizedIndexOperations(seizedIndexOpPool)
@@ -763,7 +737,7 @@ public:
UintR accumulatingIndexOp;
UintR executingIndexOp;
UintR tcIndxSendArray[6];
- ArrayList<TcSeizedIndexOperation> theSeizedIndexOperations;
+ ArrayList<TcIndexOperation> theSeizedIndexOperations;
};
typedef Ptr<ApiConnectRecord> ApiConnectRecordPtr;
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
index 59c8237f20a..f99b4bf15af 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
@@ -65,7 +65,6 @@ void Dbtc::initData()
c_theFiredTriggerPool.setSize(c_maxNumberOfFiredTriggers);
c_theIndexPool.setSize(c_maxNumberOfIndexes);
c_theIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
- c_theSeizedIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
c_theAttributeBufferPool.setSize(c_transactionBufferSpace);
c_firedTriggerHash.setSize((c_maxNumberOfFiredTriggers+10)/10);
}//Dbtc::initData()
@@ -85,7 +84,7 @@ void Dbtc::initRecords()
for(unsigned i = 0; i<capiConnectFilesize; i++) {
p = &apiConnectRecord[i];
new (p) ApiConnectRecord(c_theFiredTriggerPool,
- c_theSeizedIndexOperationPool);
+ c_theIndexOperationPool);
}
// Init all fired triggers
DLFifoList<TcFiredTriggerData> triggers(c_theFiredTriggerPool);
@@ -177,7 +176,6 @@ Dbtc::Dbtc(const class Configuration & conf):
c_maxNumberOfFiredTriggers(0),
c_theIndexes(c_theIndexPool),
c_maxNumberOfIndexes(0),
- c_theIndexOperations(c_theIndexOperationPool),
c_maxNumberOfIndexOperations(0),
m_commitAckMarkerHash(m_commitAckMarkerPool)
{
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index c8260223004..38d514047b8 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -11368,18 +11368,18 @@ void Dbtc::execTCINDXREQ(Signal* signal)
jam();
// This is a newly started transaction, clean-up
releaseAllSeizedIndexOperations(regApiPtr);
+
+ regApiPtr->transid[0] = tcIndxReq->transId1;
+ regApiPtr->transid[1] = tcIndxReq->transId2;
}//if
- if (!seizeIndexOperation(regApiPtr, indexOpPtr)) {
+
+ if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
jam();
// Failed to allocate index operation
- TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
-
- tcIndxRef->connectPtr = tcIndxReq->senderData;
- tcIndxRef->transId[0] = regApiPtr->transid[0];
- tcIndxRef->transId[1] = regApiPtr->transid[1];
- tcIndxRef->errorCode = 4000;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
+ terrorCode = 288;
+ regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
+ apiConnectptr = transPtr;
+ abortErrorLab(signal);
return;
}
TcIndexOperation* indexOp = indexOpPtr.p;
@@ -11514,15 +11514,17 @@ void Dbtc::execINDXKEYINFO(Signal* signal)
TcIndexOperationPtr indexOpPtr;
TcIndexOperation* indexOp;
- indexOpPtr.i = regApiPtr->accumulatingIndexOp;
- indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
- if (saveINDXKEYINFO(signal,
- indexOp,
- src,
- keyInfoLength)) {
- jam();
- // We have received all we need
- readIndexTable(signal, regApiPtr, indexOp);
+ if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
+ {
+ indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
+ if (saveINDXKEYINFO(signal,
+ indexOp,
+ src,
+ keyInfoLength)) {
+ jam();
+ // We have received all we need
+ readIndexTable(signal, regApiPtr, indexOp);
+ }
}
}
@@ -11545,15 +11547,17 @@ void Dbtc::execINDXATTRINFO(Signal* signal)
TcIndexOperationPtr indexOpPtr;
TcIndexOperation* indexOp;
- indexOpPtr.i = regApiPtr->accumulatingIndexOp;
- indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
- if (saveINDXATTRINFO(signal,
- indexOp,
- src,
- attrInfoLength)) {
- jam();
- // We have received all we need
- readIndexTable(signal, regApiPtr, indexOp);
+ if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
+ {
+ indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
+ if (saveINDXATTRINFO(signal,
+ indexOp,
+ src,
+ attrInfoLength)) {
+ jam();
+ // We have received all we need
+ readIndexTable(signal, regApiPtr, indexOp);
+ }
}
}
@@ -11578,7 +11582,7 @@ bool Dbtc::saveINDXKEYINFO(Signal* signal,
releaseIndexOperation(apiConnectptr.p, indexOp);
terrorCode = 4000;
abortErrorLab(signal);
- return true;
+ return false;
}
if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
jam();
@@ -11611,7 +11615,7 @@ bool Dbtc::saveINDXATTRINFO(Signal* signal,
releaseIndexOperation(apiConnectptr.p, indexOp);
terrorCode = 4000;
abortErrorLab(signal);
- return true;
+ return false;
}
if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
jam();
@@ -11671,7 +11675,7 @@ void Dbtc::execTCKEYCONF(Signal* signal)
jamEntry();
indexOpPtr.i = tcKeyConf->apiConnectPtr;
- TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
+ TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
Uint32 confInfo = tcKeyConf->confInfo;
/**
@@ -11760,7 +11764,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
jamEntry();
indexOpPtr.i = tcKeyRef->connectPtr;
- TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
+ TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
indexOpPtr.p = indexOp;
if (!indexOp) {
jam();
@@ -11861,7 +11865,7 @@ void Dbtc::execTRANSID_AI(Signal* signal)
jamEntry();
TcIndexOperationPtr indexOpPtr;
indexOpPtr.i = transIdAI->connectPtr;
- TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
+ TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
indexOpPtr.p = indexOp;
if (!indexOp) {
jam();
@@ -11969,7 +11973,7 @@ void Dbtc::execTCROLLBACKREP(Signal* signal)
jamEntry();
TcIndexOperationPtr indexOpPtr;
indexOpPtr.i = tcRollbackRep->connectPtr;
- TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
+ TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
indexOpPtr.p = indexOp;
tcRollbackRep = (TcRollbackRep *)signal->getDataPtrSend();
tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
@@ -12297,16 +12301,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
TcIndexOperationPtr& indexOpPtr)
{
- bool seizeOk;
-
- seizeOk = c_theIndexOperations.seize(indexOpPtr);
- if (seizeOk) {
- jam();
- TcSeizedIndexOperationPtr seizedIndexOpPtr;
- seizeOk &= regApiPtr->theSeizedIndexOperations.seizeId(seizedIndexOpPtr,
- indexOpPtr.i);
- }
- return seizeOk;
+ return regApiPtr->theSeizedIndexOperations.seize(indexOpPtr);
}
void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
@@ -12320,18 +12315,16 @@ void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
indexOp->expectedTransIdAI = 0;
indexOp->transIdAI.release();
regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
- c_theIndexOperations.release(indexOp->indexOpId);
}
void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
{
- TcSeizedIndexOperationPtr seizedIndexOpPtr;
+ TcIndexOperationPtr seizedIndexOpPtr;
regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
while(seizedIndexOpPtr.i != RNIL) {
jam();
- TcIndexOperation* indexOp =
- c_theIndexOperations.getPtr(seizedIndexOpPtr.i);
+ TcIndexOperation* indexOp = seizedIndexOpPtr.p;
indexOp->indexOpState = IOS_NOOP;
indexOp->expectedKeyInfo = 0;
@@ -12340,7 +12333,6 @@ void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
indexOp->attrInfo.release();
indexOp->expectedTransIdAI = 0;
indexOp->transIdAI.release();
- c_theIndexOperations.release(seizedIndexOpPtr.i);
regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
}
regApiPtr->theSeizedIndexOperations.release();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
index cbd56c3281f..470b98fd04c 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
@@ -443,6 +443,7 @@ Dbtup::commitRecord(Signal* signal,
saveAttributeMask.bitOR(befOpPtr.p->changeMask);
befOpPtr.p->changeMask.clear();
befOpPtr.p->changeMask.bitOR(attributeMask);
+ befOpPtr.p->gci = regOperPtr->gci;
operPtr.p = befOpPtr.p;
checkDetachedTriggers(signal,
@@ -480,6 +481,7 @@ Dbtup::commitRecord(Signal* signal,
befOpPtr.p->pageOffset = befOpPtr.p->pageOffsetC;
befOpPtr.p->fragPageId = befOpPtr.p->fragPageIdC;
befOpPtr.p->pageIndex = befOpPtr.p->pageIndexC;
+ befOpPtr.p->gci = regOperPtr->gci;
operPtr.p = befOpPtr.p;
checkDetachedTriggers(signal,
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index f76440a462a..b3fc6e04d6c 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -799,7 +799,11 @@ AsyncFile::rmrfReq(Request * request, char * path, bool removePath){
request->error = errno;
return;
}
+#if defined(__INTEL_COMPILER)
+ struct dirent64 * dp;
+#else
struct dirent * dp;
+#endif
while ((dp = readdir(dirp)) != NULL){
if ((strcmp(".", dp->d_name) != 0) && (strcmp("..", dp->d_name) != 0)) {
BaseString::snprintf(path_add, (size_t)path_max_copy, "%s%s",
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index 35cd3f099d9..e4ead4ce34d 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -130,7 +130,7 @@ ErrorReporter::formatMessage(ErrorCategory type,
"Date/Time: %s\nType of error: %s\n"
"Message: %s\nFault ID: %d\nProblem data: %s"
"\nObject of reference: %s\nProgramName: %s\n"
- "ProcessID: %d\nTraceFile: %s\n***EOM***\n",
+ "ProcessID: %d\nTraceFile: %s\n%s\n***EOM***\n",
formatTimeStampString() ,
errorType[type],
lookupErrorMessage(faultID),
@@ -139,7 +139,8 @@ ErrorReporter::formatMessage(ErrorCategory type,
objRef,
my_progname,
processId,
- theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>");
+ theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>",
+ NDB_VERSION_STRING);
// Add trailing blanks to get a fixed lenght of the message
while (strlen(messptr) <= MESSAGE_LENGTH-3){
@@ -237,6 +238,11 @@ WriteMessage(ErrorCategory thrdType, int thrdMessageID,
// Create a new file, and skip the first 69 bytes,
// which are info about the current offset
stream = fopen(theErrorFileName, "w");
+ if(stream == NULL)
+ {
+ fprintf(stderr,"Unable to open error log file: %s\n", theErrorFileName);
+ return -1;
+ }
fprintf(stream, "%s%u%s", "Current byte-offset of file-pointer is: ", 69,
" \n\n\n");
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index ab32de5b9ca..e5e00b78bfa 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -892,7 +892,10 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
args.put("initialstart", initial);
args.put("nostart", nostart);
const Properties *reply;
+ const int timeout = handle->read_timeout;
+ handle->read_timeout= 5*60*1000; // 5 minutes
reply = ndb_mgm_call(handle, restart_reply, "restart all", &args);
+ handle->read_timeout= timeout;
CHECK_REPLY(reply, -1);
BaseString result;
@@ -925,7 +928,10 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
args.put("nostart", nostart);
const Properties *reply;
+ const int timeout = handle->read_timeout;
+ handle->read_timeout= 5*60*1000; // 5 minutes
reply = ndb_mgm_call(handle, restart_reply, "restart node", &args);
+ handle->read_timeout= timeout;
if(reply != NULL) {
BaseString result;
reply->get("result", result);
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index 71938e27037..42b3b01bca1 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -66,6 +66,7 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade):
{
ndbSetOwnVersion();
clusterMgrThreadMutex = NdbMutex_Create();
+ noOfAliveNodes= 0;
noOfConnectedNodes= 0;
theClusterMgrThread= 0;
}
@@ -336,9 +337,9 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
node.m_state = apiRegConf->nodeState;
if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED ||
node.m_state.startLevel == NodeState::SL_SINGLEUSER)){
- node.m_alive = true;
+ set_node_alive(node, true);
} else {
- node.m_alive = false;
+ set_node_alive(node, false);
}//if
node.hbSent = 0;
node.hbCounter = 0;
@@ -361,7 +362,7 @@ ClusterMgr::execAPI_REGREF(const Uint32 * theData){
assert(node.defined == true);
node.compatible = false;
- node.m_alive = false;
+ set_node_alive(node, false);
node.m_state = NodeState::SL_NOTHING;
node.m_info.m_version = ref->version;
@@ -446,7 +447,7 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){
Node & theNode = theNodes[nodeId];
- theNode.m_alive = false;
+ set_node_alive(theNode, false);
theNode.m_info.m_connectCount ++;
if(theNode.connected)
@@ -462,8 +463,8 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){
}
theNode.nfCompleteRep = false;
-
- if(noOfConnectedNodes == 0){
+ if(noOfAliveNodes == 0)
+ {
NFCompleteRep rep;
for(Uint32 i = 1; i<MAX_NODES; i++){
if(theNodes[i].defined && theNodes[i].nfCompleteRep == false){
diff --git a/ndb/src/ndbapi/ClusterMgr.hpp b/ndb/src/ndbapi/ClusterMgr.hpp
index cc3cf66c8aa..d75b820e9cb 100644
--- a/ndb/src/ndbapi/ClusterMgr.hpp
+++ b/ndb/src/ndbapi/ClusterMgr.hpp
@@ -80,6 +80,7 @@ public:
Uint32 getNoOfConnectedNodes() const;
private:
+ Uint32 noOfAliveNodes;
Uint32 noOfConnectedNodes;
Node theNodes[MAX_NODES];
NdbThread* theClusterMgrThread;
@@ -100,6 +101,19 @@ private:
void execAPI_REGREF (const Uint32 * theData);
void execNODE_FAILREP (const Uint32 * theData);
void execNF_COMPLETEREP(const Uint32 * theData);
+
+ inline void set_node_alive(Node& node, bool alive){
+ if(node.m_alive && !alive)
+ {
+ assert(noOfAliveNodes);
+ noOfAliveNodes--;
+ }
+ else if(!node.m_alive && alive)
+ {
+ noOfAliveNodes++;
+ }
+ node.m_alive = alive;
+ }
};
inline
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index c01ce823dc0..5efef1b0112 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -764,7 +764,7 @@ Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl *table= info->m_table_impl;
Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
- DBUG_PRINT("info", ("value %u", tupleId));
+ DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -776,7 +776,7 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
- DBUG_PRINT("info", ("value %u", tupleId));
+ DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -796,7 +796,8 @@ Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize)
if ( theFirstTupleId[aTableId] != theLastTupleId[aTableId] )
{
theFirstTupleId[aTableId]++;
- DBUG_PRINT("info", ("next cached value %u", theFirstTupleId[aTableId]));
+ DBUG_PRINT("info", ("next cached value %ul",
+ (ulong) theFirstTupleId[aTableId]));
DBUG_RETURN(theFirstTupleId[aTableId]);
}
else // theFirstTupleId == theLastTupleId
@@ -817,7 +818,7 @@ Ndb::readAutoIncrementValue(const char* aTableName)
DBUG_RETURN(~(Uint64)0);
}
Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
- DBUG_PRINT("info", ("value %u", tupleId));
+ DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -829,7 +830,7 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
- DBUG_PRINT("info", ("value %u", tupleId));
+ DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index 6bbd38c9bbb..be9e5084a47 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -173,7 +173,7 @@ ErrorBundle ErrorCodes[] = {
{ 4021, TR, "Out of Send Buffer space in NDB API" },
{ 4022, TR, "Out of Send Buffer space in NDB API" },
{ 4032, TR, "Out of Send Buffer space in NDB API" },
-
+ { 288, TR, "Out of index operations in transaction coordinator (increase MaxNoOfConcurrentIndexOperations)" },
/**
* InsufficientSpace
*/
diff --git a/ndb/test/include/CpcClient.hpp b/ndb/test/include/CpcClient.hpp
index 1655bc57b56..8d8e079d219 100644
--- a/ndb/test/include/CpcClient.hpp
+++ b/ndb/test/include/CpcClient.hpp
@@ -56,6 +56,7 @@ public:
BaseString m_stdout;
BaseString m_stderr;
BaseString m_ulimit;
+ BaseString m_shutdown_options;
};
private:
diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp
index 1ce934a19ca..6ef3da2d760 100644
--- a/ndb/test/ndbapi/testNodeRestart.cpp
+++ b/ndb/test/ndbapi/testNodeRestart.cpp
@@ -359,7 +359,7 @@ int runLateCommit(NDBT_Context* ctx, NDBT_Step* step){
if(hugoOps.startTransaction(pNdb) != 0)
return NDBT_FAILED;
- if(hugoOps.pkUpdateRecord(pNdb, 1) != 0)
+ if(hugoOps.pkUpdateRecord(pNdb, 1, 128) != 0)
return NDBT_FAILED;
if(hugoOps.execute_NoCommit(pNdb) != 0)
diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am
index 1067328dcc3..60d64a7697f 100644
--- a/ndb/test/run-test/Makefile.am
+++ b/ndb/test/run-test/Makefile.am
@@ -6,7 +6,12 @@ include $(top_srcdir)/ndb/config/type_util.mk.am
include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
test_PROGRAMS = atrt
-test_DATA=daily-basic-tests.txt daily-devel-tests.txt 16node-tests.txt
+test_DATA=daily-basic-tests.txt daily-devel-tests.txt 16node-tests.txt \
+ conf-daily-basic-ndbmaster.txt \
+ conf-daily-basic-shark.txt \
+ conf-daily-devel-ndbmaster.txt \
+ conf-daily-sql-ndbmaster.txt \
+ conf-daily-basic-dl145a.txt
test_SCRIPTS=atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \
atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh
diff --git a/ndb/test/run-test/conf-daily-basic-dl145a.txt b/ndb/test/run-test/conf-daily-basic-dl145a.txt
new file mode 100644
index 00000000000..d8cf8d34d82
--- /dev/null
+++ b/ndb/test/run-test/conf-daily-basic-dl145a.txt
@@ -0,0 +1,19 @@
+baseport: 14000
+basedir: /home/ndbdev/autotest/run
+mgm: CHOOSE_host1
+ndb: CHOOSE_host2 CHOOSE_host3
+api: CHOOSE_host1 CHOOSE_host1 CHOOSE_host1
+-- cluster config
+[DB DEFAULT]
+NoOfReplicas: 2
+IndexMemory: 100M
+DataMemory: 300M
+BackupMemory: 64M
+MaxNoOfConcurrentScans: 100
+DataDir: .
+FileSystemPath: /home/ndbdev/autotest/run
+
+[MGM DEFAULT]
+PortNumber: 14000
+ArbitrationRank: 1
+DataDir: .
diff --git a/ndb/test/run-test/conf-daily-basic-ndbmaster.txt b/ndb/test/run-test/conf-daily-basic-ndbmaster.txt
new file mode 100644
index 00000000000..bcd809593f3
--- /dev/null
+++ b/ndb/test/run-test/conf-daily-basic-ndbmaster.txt
@@ -0,0 +1,19 @@
+baseport: 14000
+basedir: /space/autotest
+mgm: CHOOSE_host1
+ndb: CHOOSE_host2 CHOOSE_host3 CHOOSE_host2 CHOOSE_host3
+api: CHOOSE_host1 CHOOSE_host1 CHOOSE_host1
+-- cluster config
+[DB DEFAULT]
+NoOfReplicas: 2
+IndexMemory: 100M
+DataMemory: 300M
+BackupMemory: 64M
+MaxNoOfConcurrentScans: 100
+DataDir: .
+FileSystemPath: /space/autotest/run
+
+[MGM DEFAULT]
+PortNumber: 14000
+ArbitrationRank: 1
+DataDir: .
diff --git a/ndb/test/run-test/conf-daily-basic-shark.txt b/ndb/test/run-test/conf-daily-basic-shark.txt
new file mode 100644
index 00000000000..6d1f8b64f44
--- /dev/null
+++ b/ndb/test/run-test/conf-daily-basic-shark.txt
@@ -0,0 +1,19 @@
+baseport: 14000
+basedir: /space/autotest
+mgm: CHOOSE_host1
+ndb: CHOOSE_host1 CHOOSE_host1
+api: CHOOSE_host1 CHOOSE_host1 CHOOSE_host1
+-- cluster config
+[DB DEFAULT]
+NoOfReplicas: 2
+IndexMemory: 100M
+DataMemory: 300M
+BackupMemory: 64M
+MaxNoOfConcurrentScans: 100
+DataDir: .
+FileSystemPath: /space/autotest/run
+
+[MGM DEFAULT]
+PortNumber: 14000
+ArbitrationRank: 1
+DataDir: .
diff --git a/ndb/test/run-test/conf-daily-devel-ndbmaster.txt b/ndb/test/run-test/conf-daily-devel-ndbmaster.txt
new file mode 100644
index 00000000000..8b340e6a39d
--- /dev/null
+++ b/ndb/test/run-test/conf-daily-devel-ndbmaster.txt
@@ -0,0 +1,19 @@
+baseport: 16000
+basedir: /space/autotest
+mgm: CHOOSE_host1
+ndb: CHOOSE_host2 CHOOSE_host3 CHOOSE_host2 CHOOSE_host3
+api: CHOOSE_host1 CHOOSE_host1 CHOOSE_host1
+-- cluster config
+[DB DEFAULT]
+NoOfReplicas: 2
+IndexMemory: 100M
+DataMemory: 300M
+BackupMemory: 64M
+MaxNoOfConcurrentScans: 100
+DataDir: .
+FileSystemPath: /space/autotest/run
+
+[MGM DEFAULT]
+PortNumber: 16000
+ArbitrationRank: 1
+DataDir: .
diff --git a/ndb/test/run-test/conf-daily-sql-ndbmaster.txt b/ndb/test/run-test/conf-daily-sql-ndbmaster.txt
new file mode 100644
index 00000000000..0d6a99f8d48
--- /dev/null
+++ b/ndb/test/run-test/conf-daily-sql-ndbmaster.txt
@@ -0,0 +1,20 @@
+baseport: 16000
+basedir: /space/autotest
+mgm: CHOOSE_host1
+ndb: CHOOSE_host2 CHOOSE_host3
+mysqld: CHOOSE_host1 CHOOSE_host4
+mysql: CHOOSE_host1 CHOOSE_host1 CHOOSE_host1 CHOOSE_host1 CHOOSE_host1 CHOOSE_host1 CHOOSE_host4 CHOOSE_host4 CHOOSE_host4 CHOOSE_host4 CHOOSE_host4 CHOOSE_host4
+-- cluster config
+[DB DEFAULT]
+NoOfReplicas: 2
+IndexMemory: 100M
+DataMemory: 300M
+BackupMemory: 64M
+MaxNoOfConcurrentScans: 100
+DataDir: .
+FileSystemPath: /space/autotest/run
+
+[MGM DEFAULT]
+PortNumber: 16000
+ArbitrationRank: 1
+DataDir: .
diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp
index 02c2cc862a3..0b0b7472a19 100644
--- a/ndb/test/run-test/main.cpp
+++ b/ndb/test/run-test/main.cpp
@@ -116,10 +116,7 @@ main(int argc, const char ** argv){
*/
if(restart){
g_logger.info("(Re)starting ndb processes");
- if(!stop_processes(g_config, atrt_process::NDB_MGM))
- goto end;
-
- if(!stop_processes(g_config, atrt_process::NDB_DB))
+ if(!stop_processes(g_config, ~0))
goto end;
if(!start_processes(g_config, atrt_process::NDB_MGM))
@@ -142,6 +139,9 @@ main(int argc, const char ** argv){
goto end;
started:
+ if(!start_processes(g_config, p_servers))
+ goto end;
+
g_logger.info("Ndb start completed");
}
@@ -158,9 +158,6 @@ main(int argc, const char ** argv){
if(!setup_test_case(g_config, test_case))
goto end;
- if(!start_processes(g_config, p_servers))
- goto end;
-
if(!start_processes(g_config, p_clients))
goto end;
@@ -201,9 +198,6 @@ main(int argc, const char ** argv){
if(!stop_processes(g_config, p_clients))
goto end;
- if(!stop_processes(g_config, p_servers))
- goto end;
-
if(!gather_result(g_config, &result))
goto end;
@@ -454,6 +448,7 @@ setup_config(atrt_config& config){
proc.m_proc.m_runas = proc.m_host->m_user;
proc.m_proc.m_ulimit = "c:unlimited";
proc.m_proc.m_env.assfmt("MYSQL_BASE_DIR=%s", dir.c_str());
+ proc.m_proc.m_shutdown_options = "";
proc.m_hostname = proc.m_host->m_hostname;
proc.m_ndb_mgm_port = g_default_base_port;
if(split1[0] == "mgm"){
@@ -476,21 +471,19 @@ setup_config(atrt_config& config){
proc.m_proc.m_path.assign(dir).append("/libexec/mysqld");
proc.m_proc.m_args = "--core-file --ndbcluster";
proc.m_proc.m_cwd.appfmt("%d.mysqld", index);
- if(mysql_port_offset > 0 || g_mysqld_use_base){
- // setup mysql specific stuff
- const char * basedir = proc.m_proc.m_cwd.c_str();
- proc.m_proc.m_args.appfmt("--datadir=%s", basedir);
- proc.m_proc.m_args.appfmt("--pid-file=%s/mysql.pid", basedir);
- proc.m_proc.m_args.appfmt("--socket=%s/mysql.sock", basedir);
- proc.m_proc.m_args.appfmt("--port=%d",
- g_default_base_port-(++mysql_port_offset));
- }
+ proc.m_proc.m_shutdown_options = "SIGKILL"; // not nice
} else if(split1[0] == "api"){
proc.m_type = atrt_process::NDB_API;
proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_api");
proc.m_proc.m_path = "";
proc.m_proc.m_args = "";
proc.m_proc.m_cwd.appfmt("%d.ndb_api", index);
+ } else if(split1[0] == "mysql"){
+ proc.m_type = atrt_process::MYSQL_CLIENT;
+ proc.m_proc.m_name.assfmt("%d-%s", index, "mysql");
+ proc.m_proc.m_path = "";
+ proc.m_proc.m_args = "";
+ proc.m_proc.m_cwd.appfmt("%d.mysql", index);
} else {
g_logger.critical("%s:%d: Unhandled process type: %s",
g_process_config_filename, lineno,
@@ -913,6 +906,11 @@ read_test_case(FILE * file, atrt_testcase& tc, int& line){
tc.m_report= true;
else
tc.m_report= false;
+
+ if(p.get("run-all", &mt) && strcmp(mt, "yes") == 0)
+ tc.m_run_all= true;
+ else
+ tc.m_run_all= false;
return true;
}
@@ -928,16 +926,17 @@ setup_test_case(atrt_config& config, const atrt_testcase& tc){
size_t i = 0;
for(; i<config.m_processes.size(); i++){
atrt_process & proc = config.m_processes[i];
- if(proc.m_type == atrt_process::NDB_API){
+ if(proc.m_type == atrt_process::NDB_API || proc.m_type == atrt_process::MYSQL_CLIENT){
proc.m_proc.m_path.assfmt("%s/bin/%s", proc.m_host->m_base_dir.c_str(),
tc.m_command.c_str());
proc.m_proc.m_args.assign(tc.m_args);
- break;
+ if(!tc.m_run_all)
+ break;
}
}
for(i++; i<config.m_processes.size(); i++){
atrt_process & proc = config.m_processes[i];
- if(proc.m_type == atrt_process::NDB_API){
+ if(proc.m_type == atrt_process::NDB_API || proc.m_type == atrt_process::MYSQL_CLIENT){
proc.m_proc.m_path.assign("");
proc.m_proc.m_args.assign("");
}
diff --git a/ndb/test/run-test/make-config.sh b/ndb/test/run-test/make-config.sh
index 5394b0654d4..1321ce4e9f0 100755
--- a/ndb/test/run-test/make-config.sh
+++ b/ndb/test/run-test/make-config.sh
@@ -1,465 +1,101 @@
#!/bin/sh
-# NAME
-# make-config.sh - Makes a config file for mgm server
-#
-# SYNOPSIS
-# make-config.sh [ -t <template> ] [-s] [ -m <machine conf> [ -d <directory> ]
-#
-# DESCRIPTION
-#
-# OPTIONS
-#
-# EXAMPLES
-#
-#
-# ENVIRONMENT
-# NDB_PROJ_HOME Home dir for ndb
-#
-# FILES
-# $NDB_PROJ_HOME/lib/funcs.sh general shell script functions
-#
-#
-# SEE ALSO
-#
-# DIAGNOSTICTS
-#
-# VERSION
-# 1.0
-# 1.1 021112 epesson: Adapted for new mgmt server in NDB 2.00
-#
-# AUTHOR
-# Jonas Oreland
-#
-# CHANGES
-# also generate ndbnet config
-#
-progname=`basename $0`
-synopsis="make-config.sh [ -t template ] [ -m <machine conf> ] [ -d <dst directory> ][-s] [<mgm host>]"
+baseport=""
+basedir=""
+proc_no=1
+node_id=1
-#: ${NDB_PROJ_HOME:?} # If undefined, exit with error message
+d_file=/tmp/d.$$
+dir_file=/tmp/dirs.$$
+config_file=/tmp/config.$$
+cluster_file=/tmp/cluster.$$
-#: ${NDB_LOCAL_BUILD_OPTIONS:=--} # If undef, set to --. Keeps getopts happy.
- # You may have to experiment a bit
- # to get quoting right (if you need it).
-
-
-#. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff
-trace() {
- echo $* 1>&2
-}
-syndie() {
- trace $*
- exit 1
-}
-
-# defaults for options related variables
-#
-
-mgm_nodes=0
-ndb_nodes=0
-api_nodes=0
-uniq_id=$$.$$
-own_host=`hostname`
-dst_dir=""
-template=/dev/null
-machines=/dev/null
-verbose=yes
-
-# used if error when parsing the options environment variable
-#
-env_opterr="options environment variable: <<$options>>"
-
-# Option parsing, for the options variable as well as the command line.
-#
-# We want to be able to set options in an environment variable,
-# as well as on the command line. In order not to have to repeat
-# the same getopts information twice, we loop two times over the
-# getopts while loop. The first time, we process options from
-# the options environment variable, the second time we process
-# options from the command line.
-#
-# The things to change are the actual options and what they do.
-#
-add_node(){
- no=$1; shift
+add_procs(){
type=$1; shift
- echo $* | awk 'BEGIN{FS=":";}{h=$1; if(h=="localhost") h="'$own_host'";
- printf("%s_%d_host=%s\n", "'$type'", "'$no'", h);
- if(NF>1 && $2!="") printf("%s_%d_port=%d\n",
- "'$type'", "'$no'", $2);
- if(NF>2 && $3!="") printf("%s_%d_dir=%s\n",
- "'$type'", "'$no'", $3);
- }'
-}
-
-
-add_mgm_node(){
- mgm_nodes=`cat /tmp/mgm_nodes.$uniq_id | grep "_host=" | wc -l`
- mgm_nodes=`expr $mgm_nodes + 1`
- while [ $# -gt 0 ]
- do
- add_node ${mgm_nodes} mgm_node $1 >> /tmp/mgm_nodes.$uniq_id
- shift
- mgm_nodes=`expr $mgm_nodes + 1`
- done
-}
-
-add_ndb_node(){
- ndb_nodes=`cat /tmp/ndb_nodes.$uniq_id | grep "_host=" | wc -l`
- ndb_nodes=`expr $ndb_nodes + 1`
- while [ $# -gt 0 ]
- do
- add_node ${ndb_nodes} ndb_node $1 >> /tmp/ndb_nodes.$uniq_id
- shift
- ndb_nodes=`expr $ndb_nodes + 1`
- done
-}
-
-add_api_node(){
- api_nodes=`cat /tmp/api_nodes.$uniq_id | grep "_host=" |wc -l`
- api_nodes=`expr $api_nodes + 1`
- while [ $# -gt 0 ]
- do
- add_node ${api_nodes} api_node $1 >> /tmp/api_nodes.$uniq_id
- shift
- api_nodes=`expr $api_nodes + 1`
- done
+ while [ $# -ne 0 ]
+ do
+ add_proc $type $1
+ shift
+ done
}
-rm -rf /tmp/mgm_nodes.$uniq_id ; touch /tmp/mgm_nodes.$uniq_id
-rm -rf /tmp/ndb_nodes.$uniq_id ; touch /tmp/ndb_nodes.$uniq_id
-rm -rf /tmp/api_nodes.$uniq_id ; touch /tmp/api_nodes.$uniq_id
-
-for optstring in "$options" "" # 1. options variable 2. cmd line
-do
-
- while getopts d:m:t:n:o:a:b:p:s i $optstring # optstring empty => no arg => cmd line
- do
- case $i in
-
- q) verbose="";; # echo important things
- t) template=$OPTARG;; # Template
- d) dst_dir=$OPTARG;; # Destination directory
- m) machines=$OPTARG;; # Machine configuration
- s) mgm_start=yes;; # Make mgm start script
- \?) syndie $env_opterr;; # print synopsis and exit
-
+add_proc (){
+ dir=""
+ conf=""
+ case $type in
+ mgm)
+ dir="ndb_mgmd"
+ conf="[ndb_mgmd]\nId: $node_id\nHostName: $2\n"
+ node_id=`expr $node_id + 1`
+ ;;
+ api)
+ dir="ndb_api"
+ conf="[api]\nId: $node_id\nHostName: $2\n"
+ node_id=`expr $node_id + 1`
+ ;;
+ ndb)
+ dir="ndbd"
+ conf="[ndbd]\nId: $node_id\nHostName: $2\n"
+ node_id=`expr $node_id + 1`
+ ;;
+ mysqld)
+ dir="mysqld"
+ conf="[mysqld]\nId: $node_id\nHostName: $2\n"
+ node_id=`expr $node_id + 1`
+ ;;
+ mysql)
+ dir="mysql"
+ ;;
esac
- done
-
- [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmdline options
-
- env_opterr= # Round 2 should not use the value
-
-done
-shift `expr $OPTIND - 1`
-
-if [ -z "$dst_dir" ]
-then
- verbose=
-fi
-
-skip(){
- no=$1; shift
- shift $no
- echo $*
+ dir="$proc_no.$dir"
+ proc_no=`expr $proc_no + 1`
+ echo -e $dir >> $dir_file
+ if [ "$conf" ]
+ then
+ echo -e $conf >> $config_file
+ fi
}
-# --- option parsing done ---
-grep "^ndb: " $machines | while read node
-do
- node=`skip 1 $node`
- add_ndb_node $node
-done
-
-grep "^api: " $machines | while read node
-do
- node=`skip 1 $node`
- add_api_node $node
-done
-grep "^mgm: " $machines | while read node
+cnf=/dev/null
+cat $1 | while read line
do
- node=`skip 1 $node`
- add_mgm_node $node
+ case $line in
+ baseport:*) baseport=`echo $line | sed 's/baseport[ ]*:[ ]*//g'`;;
+ basedir:*) basedir=`echo $line | sed 's/basedir[ ]*:[ ]*//g'`;;
+ mgm:*) add_procs mgm `echo $line | sed 's/mgm[ ]*:[ ]*//g'`;;
+ api:*) add_procs api `echo $line | sed 's/api[ ]*:[ ]*//g'`;;
+ ndb:*) add_procs ndb `echo $line | sed 's/ndb[ ]*:[ ]*//g'`;;
+ mysqld:*) add_procs mysqld `echo $line | sed 's/mysqld[ ]*:[ ]*//g'`;;
+ mysql:*) add_procs mysql `echo $line | sed 's/mysql[ ]*:[ ]*//g'`;;
+ "-- cluster config")
+ if [ "$cnf" = "/dev/null" ]
+ then
+ cnf=$cluster_file
+ else
+ cnf=/dev/null
+ fi
+ line="";;
+ *) echo $line >> $cnf; line="";;
+ esac
+ if [ "$line" ]
+ then
+ echo $line >> $d_file
+ fi
done
-tmp=`grep "^baseport: " $machines | tail -1 | cut -d ":" -f 2`
-if [ "$tmp" ]
-then
- baseport=`echo $tmp`
-else
- syndie "Unable to find baseport"
-fi
+cat $dir_file | xargs mkdir -p
-trim(){
- echo $*
-}
-tmp=`grep "^basedir: " $machines | tail -1 | cut -d ":" -f 2`
-if [ "$tmp" ]
-then
- basedir=`trim $tmp`
-fi
-
-# -- Load enviroment --
-ndb_nodes=`cat /tmp/ndb_nodes.$uniq_id | grep "_host=" | wc -l`
-api_nodes=`cat /tmp/api_nodes.$uniq_id | grep "_host=" | wc -l`
-mgm_nodes=`cat /tmp/mgm_nodes.$uniq_id | grep "_host=" | wc -l`
-. /tmp/ndb_nodes.$uniq_id
-. /tmp/api_nodes.$uniq_id
-. /tmp/mgm_nodes.$uniq_id
-rm -f /tmp/ndb_nodes.$uniq_id /tmp/api_nodes.$uniq_id /tmp/mgm_nodes.$uniq_id
-
-# -- Verify
-trace "Verifying arguments"
-
-if [ ! -r $template ]
-then
- syndie "Unable to read template file: $template"
-fi
-
-if [ $ndb_nodes -le 0 ]
-then
- syndie "No ndb nodes specified"
-fi
-
-if [ $api_nodes -le 0 ]
-then
- syndie "No api nodes specified"
-fi
-
-if [ $mgm_nodes -gt 1 ]
-then
- syndie "More than one mgm node specified"
-fi
-
-if [ $mgm_nodes -eq 0 ]
-then
- trace "No managment server specified using `hostname`"
- mgm_nodes=1
- mgm_node_1=`hostname`
-fi
-
-if [ -n "$dst_dir" ]
-then
- mkdir -p $dst_dir
- if [ ! -d $dst_dir ]
+if [ -f $cluster_file ]
then
- syndie "Unable to create dst dir: $dst_dir"
- fi
- DST=/tmp/$uniq_id
+ cat $cluster_file $config_file >> /tmp/config2.$$
+ mv /tmp/config2.$$ $config_file
fi
-# --- option verifying done ---
-
-# Find uniq computers
-i=1
-while [ $i -le $mgm_nodes ]
-do
- echo `eval echo "\$"mgm_node_${i}_host` >> /tmp/hosts.$uniq_id
- i=`expr $i + 1`
-done
-
-i=1
-while [ $i -le $ndb_nodes ]
-do
- echo `eval echo "\$"ndb_node_${i}_host` >> /tmp/hosts.$uniq_id
- i=`expr $i + 1`
-done
-
-i=1
-while [ $i -le $api_nodes ]
-do
- echo `eval echo "\$"api_node_${i}_host` >> /tmp/hosts.$uniq_id
- i=`expr $i + 1`
+for i in `find . -type d -name '*.ndb_mgmd'`
+ do
+ cp $config_file $i/config.ini
done
-sort -u -o /tmp/hosts.$uniq_id /tmp/hosts.$uniq_id
-
-get_computer_id(){
- grep -w -n $1 /tmp/hosts.$uniq_id | cut -d ":" -f 1
-}
-
-get_mgm_computer_id(){
- a=`eval echo "\$"mgm_node_${1}_host`
- get_computer_id $a
-}
-
-get_ndb_computer_id(){
- a=`eval echo "\$"ndb_node_${1}_host`
- get_computer_id $a
-}
-
-get_api_computer_id(){
- a=`eval echo "\$"api_node_${1}_host`
- get_computer_id $a
-}
-
-# -- Write config files --
-
-mgm_port=$baseport
-
-(
- i=1
- #echo "COMPUTERS"
- cat /tmp/hosts.$uniq_id | while read host
- do
- echo "[COMPUTER]"
- echo "Id: $i"
- echo "ByteOrder: Big"
- echo "HostName: $host"
- echo
- i=`expr $i + 1`
- done
-
- node_id=1
- echo
-
- # Mgm process
- echo
- echo "[MGM]"
- echo "Id: $node_id"
- echo "ExecuteOnComputer: `get_mgm_computer_id 1`"
- echo "PortNumber: $mgm_port"
- node_id=`expr $node_id + 1`
-
- # Ndb processes
- i=1
- ndb_nodes=`trim $ndb_nodes`
- while [ $i -le $ndb_nodes ]
- do
- echo
- echo "[DB]"
- echo "Id: $node_id"
- echo "ExecuteOnComputer: `get_ndb_computer_id $i`"
- echo "FileSystemPath: $basedir/run/node-${node_id}-fs"
- i=`expr $i + 1`
- node_id=`expr $node_id + 1`
- done
-
- # API processes
- i=1
- while [ $i -le $api_nodes ]
- do
- echo
- echo "[API]"
- echo "Id: $node_id"
- echo "ExecuteOnComputer: `get_api_computer_id $i`"
- i=`expr $i + 1`
- node_id=`expr $node_id + 1`
- done
-
- # Connections
- current_port=`expr $mgm_port + 1`
- echo
-
- # Connect Mgm with all ndb-nodes
- i=1
- while [ $i -le $ndb_nodes ]
- do
- echo
- echo "[TCP]"
- echo "NodeId1: 1"
- echo "NodeId2: `expr $i + 1`"
- echo "PortNumber: $current_port"
- i=`expr $i + 1`
- current_port=`expr $current_port + 1`
- done
-
- # Connect All ndb processes with all ndb processes
- i=1
- while [ $i -le $ndb_nodes ]
- do
- j=`expr $i + 1`
- while [ $j -le $ndb_nodes ]
- do
- echo
- echo "[TCP]"
- echo "NodeId1: `expr $i + 1`"
- echo "NodeId2: `expr $j + 1`"
- echo "PortNumber: $current_port"
- j=`expr $j + 1`
- current_port=`expr $current_port + 1`
- done
- i=`expr $i + 1`
- done
-
- # Connect all ndb-nodes with all api nodes
- i=1
- while [ $i -le $ndb_nodes ]
- do
- j=1
- while [ $j -le $api_nodes ]
- do
- echo
- echo "[TCP]"
- echo "NodeId1: `expr $i + 1`"
- echo "NodeId2: `expr $j + $ndb_nodes + 1`"
- echo "PortNumber: $current_port"
- j=`expr $j + 1`
- current_port=`expr $current_port + 1`
- done
- i=`expr $i + 1`
- done
- echo
-) > $DST
-
-trace "Init config file done"
-
-if [ -z "$dst_dir" ]
-then
- cat $DST
- rm -f $DST
- rm -f /tmp/hosts.$uniq_id
- exit 0
-fi
-
-###
-# Create Ndb.cfg files
-
-# nodeid=2;host=localhost:2200
-
-# Mgm node
-mkcfg(){
- mkdir -p $dst_dir/${2}.ndb_${1}
- (
- echo "OwnProcessId $2"
- echo "host://${mgm_node_1_host}:${mgm_port}"
- ) > $dst_dir/${2}.ndb_${1}/Ndb.cfg
- if [ $1 = "db" ]
- then
- mkdir $dst_dir/node-${2}-fs
- fi
-}
-
-mkcfg mgm 1
-cat $DST > $dst_dir/1.ndb_mgm/initconfig.txt
-
-trace "Creating Ndb.cfg for ndb nodes"
-
-current_node=2
-i=1
-while [ $i -le $ndb_nodes ]
-do
- mkcfg db ${current_node}
- i=`expr $i + 1`
- current_node=`expr $current_node + 1`
-done
-
-trace "Creating Ndb.cfg for api nodes"
-
-i=1
-while [ $i -le $api_nodes ]
-do
- mkcfg api ${current_node}
- i=`expr $i + 1`
- current_node=`expr $current_node + 1`
-done
-
-rm -f $DST
-rm -f /tmp/hosts.$uniq_id
-
-
-exit 0
-# vim: set sw=4:
+mv $d_file d.txt
+rm -f $config_file $dir_file $cluster_file
diff --git a/ndb/test/run-test/ndb-autotest.sh b/ndb/test/run-test/ndb-autotest.sh
index 397df97d52f..f1c83f079cd 100755
--- a/ndb/test/run-test/ndb-autotest.sh
+++ b/ndb/test/run-test/ndb-autotest.sh
@@ -1,7 +1,7 @@
#!/bin/sh
save_args=$*
-VERSION="ndb-autotest.sh version 1.0"
+VERSION="ndb-autotest.sh version 1.04"
DATE=`date '+%Y-%m-%d'`
export DATE
@@ -71,11 +71,18 @@ then
cd $dst_place
rm -rf $run_dir/*
aclocal; autoheader; autoconf; automake
- (cd innobase; aclocal; autoheader; autoconf; automake)
- (cd bdb/dist; sh s_all)
+ if [ -d storage ]
+ then
+ (cd storage/innobase; aclocal; autoheader; autoconf; automake)
+ (cd storage/bdb/dist; sh s_all)
+ else
+ (cd innobase; aclocal; autoheader; autoconf; automake)
+ (cd bdb/dist; sh s_all)
+ fi
eval $configure --prefix=$run_dir
make
make install
+ (cd $run_dir; ./bin/mysql_install_db)
fi
###
@@ -103,7 +110,9 @@ fi
test_dir=$run_dir/mysql-test/ndb
atrt=$test_dir/atrt
html=$test_dir/make-html-reports.sh
-PATH=$test_dir:$PATH
+mkconfig=$run_dir/mysql-test/ndb/make-config.sh
+
+PATH=$run_dir/bin:$test_dir:$PATH
export PATH
filter(){
@@ -125,20 +134,16 @@ hosts=`cat /tmp/hosts.$DATE`
if [ "$deploy" ]
then
- (cd / && tar cfz /tmp/build.$DATE.tgz $run_dir )
- for i in $hosts
- do
- ok=0
- scp /tmp/build.$DATE.tgz $i:/tmp/build.$DATE.$$.tgz && \
- ssh $i "rm -rf /space/autotest/*" && \
- ssh $i "cd / && tar xfz /tmp/build.$DATE.$$.tgz" && \
- ssh $i "rm /tmp/build.$DATE.$$.tgz" && ok=1
- if [ $ok -eq 0 ]
- then
- echo "$i failed during scp/ssh, excluding"
- echo $i >> /tmp/failed.$DATE
- fi
- done
+ for i in $hosts
+ do
+ rsync -a --delete --force --ignore-errors $run_dir/ $i:$run_dir
+ ok=$?
+ if [ $ok -ne 0 ]
+ then
+ echo "$i failed during rsync, excluding"
+ echo $i >> /tmp/failed.$DATE
+ fi
+ done
fi
rm -f /tmp/build.$DATE.tgz
@@ -170,6 +175,18 @@ choose(){
cat $TMP1
rm -f $TMP1
}
+
+choose_conf(){
+ host=`hostname -s`
+ if [ -f $test_dir/conf-$1-$host.txt ]
+ then
+ echo "$test_dir/conf-$1-$host.txt"
+ elif [ -f $test_dir/conf-$1.txt ]
+ then
+ echo "$test_dir/conf-$1.txt"
+ fi
+}
+
start(){
rm -rf report.txt result* log.txt
$atrt -v -v -r -R --log-file=log.txt --testcase-file=$test_dir/$2-tests.txt &
@@ -186,11 +203,17 @@ start(){
p2=`pwd`
cd ..
tar cfz /tmp/res.$$.tgz `basename $p2`/$DATE
- scp /tmp/res.$$.tgz $result_host:$result_path
- ssh $result_host "cd $result_path && tar xfz res.$$.tgz && rm -f res.$$.tgz"
+ scp /tmp/res.$$.tgz $result_host:$result_path/res.$DATE.`hostname -s`.$2.$$.tgz
rm -f /tmp/res.$$.tgz
}
+count_hosts(){
+ cnt=`grep "CHOOSE_host" $1 |
+ awk '{for(i=1; i<=NF;i++) if(match($i, "CHOOSE_host") > 0) print $i;}' |
+ sort | uniq | wc -l`
+ echo $cnt
+}
+
p=`pwd`
for dir in $RUN
do
@@ -199,10 +222,11 @@ do
run_dir=$base_dir/run-$dir-mysql-$clone-$target
res_dir=$base_dir/result-$dir-mysql-$clone-$target/$DATE
- mkdir -p $res_dir
- rm -rf $res_dir/*
+ mkdir -p $run_dir $res_dir
+ rm -rf $res_dir/* $run_dir/*
- count=`grep -c "COMPUTER" $run_dir/1.ndb_mgmd/initconfig.template`
+ conf=`choose_conf $dir`
+ count=`count_hosts $conf`
avail_hosts=`filter /tmp/filter_hosts.$$ $hosts`
avail=`echo $avail_hosts | wc -w`
if [ $count -gt $avail ]
@@ -212,12 +236,12 @@ do
break;
fi
- run_hosts=`echo $avail_hosts| awk '{for(i=1;i<='$count';i++)print $i;}'`
- choose $run_dir/d.template $run_hosts > $run_dir/d.txt
- choose $run_dir/1.ndb_mgmd/initconfig.template $run_hosts > $run_dir/1.ndb_mgmd/config.ini
+ run_hosts=`echo $avail_hosts|awk '{for(i=1;i<='$count';i++)print $i;}'`
echo $run_hosts >> /tmp/filter_hosts.$$
-
+
cd $run_dir
+ choose $conf $run_hosts > d.tmp
+ $mkconfig d.tmp
start $dir-mysql-$clone-$target $dir $res_dir &
done
cd $p
diff --git a/ndb/test/run-test/run-test.hpp b/ndb/test/run-test/run-test.hpp
index ff7f916d4ef..7011aec33d3 100644
--- a/ndb/test/run-test/run-test.hpp
+++ b/ndb/test/run-test/run-test.hpp
@@ -69,6 +69,7 @@ struct atrt_config {
struct atrt_testcase {
bool m_report;
+ bool m_run_all;
time_t m_max_time;
BaseString m_command;
BaseString m_args;
diff --git a/ndb/test/src/CpcClient.cpp b/ndb/test/src/CpcClient.cpp
index 1d1b4fcb977..4d06b4a7ff5 100644
--- a/ndb/test/src/CpcClient.cpp
+++ b/ndb/test/src/CpcClient.cpp
@@ -282,6 +282,7 @@ convert(const Properties & src, SimpleCpcClient::Process & dst){
b &= src.get("stdout", dst.m_stdout);
b &= src.get("stderr", dst.m_stderr);
b &= src.get("ulimit", dst.m_ulimit);
+ b &= src.get("shutdown", dst.m_shutdown_options);
return b;
}
@@ -305,6 +306,7 @@ convert(const SimpleCpcClient::Process & src, Properties & dst ){
b &= dst.put("stdout", src.m_stdout.c_str());
b &= dst.put("stderr", src.m_stderr.c_str());
b &= dst.put("ulimit", src.m_ulimit.c_str());
+ b &= dst.put("shutdown", src.m_shutdown_options.c_str());
return b;
}
@@ -372,6 +374,7 @@ SimpleCpcClient::list_processes(Vector<Process> &procs, Properties& reply) {
CPC_ARG("stdout",String, Mandatory, "Redirect stdout"),
CPC_ARG("stderr",String, Mandatory, "Redirect stderr"),
CPC_ARG("ulimit",String, Mandatory, "ulimit"),
+ CPC_ARG("shutdown",String, Mandatory, "shutdown"),
CPC_END()
};
diff --git a/ndb/test/src/NDBT_ResultRow.cpp b/ndb/test/src/NDBT_ResultRow.cpp
index 8e92a57d2e4..ab8d7b07ea1 100644
--- a/ndb/test/src/NDBT_ResultRow.cpp
+++ b/ndb/test/src/NDBT_ResultRow.cpp
@@ -116,8 +116,12 @@ BaseString NDBT_ResultRow::c_str() const {
NdbOut &
operator << (NdbOut& ndbout, const NDBT_ResultRow & res) {
- for(int i = 0; i<res.cols; i++)
- ndbout << *(res.data[i]) << "\t";
+ if (res.cols != 0)
+ {
+ ndbout << *(res.data[0]);
+ for(int i = 1; i<res.cols; i++)
+ ndbout << res.ad << *(res.data[i]);
+ }
return ndbout;
}
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 17a9be17108..1f28b8e4538 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -15,6 +15,7 @@ MV="mv"
STRIP=1
DEBUG=0
SILENT=0
+MACHINE=
TMP=/tmp
SUFFIX=""
NDBCLUSTER=
@@ -26,6 +27,7 @@ parse_arguments() {
--tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;;
--suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;;
--no-strip) STRIP=0 ;;
+ --machine) MACHINE=`echo "$arg" | sed -e "s;--machine=;;"` ;;
--silent) SILENT=1 ;;
--with-ndbcluster) NDBCLUSTER=1 ;;
*)
@@ -38,6 +40,8 @@ parse_arguments() {
parse_arguments "$@"
+
+
#make
# This should really be integrated with automake and not duplicate the
@@ -294,8 +298,33 @@ if [ x$NDBCLUSTER = x1 ]; then
rm -rf $BASE/ndb-stage
fi
+# Remove vendor from $system
+system=`echo $system | sed -e 's/[a-z]*-\(.*\)/\1/g'`
+
+# Map OS names to "our" OS names (eg. darwin6.8 -> osx10.2)
+system=`echo $system | sed -e 's/darwin6.*/osx10.2/g'`
+system=`echo $system | sed -e 's/darwin7.*/osx10.3/g'`
+system=`echo $system | sed -e 's/darwin8.*/osx10.4/g'`
+system=`echo $system | sed -e 's/\(aix4.3\).*/\1/g'`
+system=`echo $system | sed -e 's/\(aix5.1\).*/\1/g'`
+system=`echo $system | sed -e 's/\(aix5.2\).*/\1/g'`
+system=`echo $system | sed -e 's/\(aix5.3\).*/\1/g'`
+system=`echo $system | sed -e 's/osf5.1b/tru64/g'`
+system=`echo $system | sed -e 's/linux-gnu/linux/g'`
+system=`echo $system | sed -e 's/solaris2.\([0-9]*\)/solaris\1/g'`
+system=`echo $system | sed -e 's/sco3.2v\(.*\)/openserver\1/g'`
+
+# Use the override --machine if present
+if [ $MACHINE != "" ] ; then
+ machine= $MACHINE
+fi
+
# Change the distribution to a long descriptive name
NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-$version-$system-$machine$SUFFIX
+
+# Print the platform name for build logs
+echo "PLATFORM NAME: $system-$machine"
+
BASE2=$TMP/$NEW_NAME
rm -r -f $BASE2
mv $BASE $BASE2
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index e76fc935b03..0eb14cd5e65 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -105,6 +105,9 @@ then
c_h="$c_h Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_h="$c_h Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_h="$c_h Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
c_h="$c_h PRIMARY KEY Host (Host,Db)"
c_h="$c_h ) engine=MyISAM"
c_h="$c_h CHARACTER SET utf8 COLLATE utf8_bin"
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index d18536e1c81..292720371c8 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -271,21 +271,25 @@ SELECT @hadCreateRoutinePriv:=1 FROM user WHERE Create_routine_priv LIKE '%';
# Create PROCEDUREs privileges (v5.0)
#
ALTER TABLE db ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv;
+ALTER TABLE host ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv;
ALTER TABLE user ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv;
#
# Alter PROCEDUREs privileges (v5.0)
#
ALTER TABLE db ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv;
+ALTER TABLE host ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv;
ALTER TABLE user ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv;
ALTER TABLE db ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv;
+ALTER TABLE host ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv;
#
# Assign create/alter routine privileges to people who have create privileges
#
UPDATE user SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv where user<>"" AND @hadCreateRoutinePriv = 0;
UPDATE db SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv, Execute_priv=Select_priv where user<>"" AND @hadCreateRoutinePriv = 0;
+UPDATE host SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv, Execute_priv=Select_priv where @hadCreateRoutinePriv = 0;
#
# Add max_user_connections resource limit
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index e1e2d4ce148..33db1eae82a 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -11,7 +11,6 @@ in_rpm=0
windows=0
defaults=""
user=""
-tmp_file=/tmp/mysql_install_db.$$
case "$1" in
--no-defaults|--defaults-file=*|--defaults-extra-file=*)
@@ -223,10 +222,8 @@ then
then
echo "Fill help tables"
fi
- echo "use mysql;" > $tmp_file
- cat $tmp_file $fill_help_tables | eval "$mysqld_install_cmd_line"
+ (echo "use mysql;"; cat $fill_help_tables) | eval "$mysqld_install_cmd_line"
res=$?
- rm $tmp_file
if test $res != 0
then
echo ""
diff --git a/server-tools/instance-manager/command.cc b/server-tools/instance-manager/command.cc
index 818c4b0cae2..73dd49ef8b8 100644
--- a/server-tools/instance-manager/command.cc
+++ b/server-tools/instance-manager/command.cc
@@ -28,6 +28,3 @@ Command::Command(Instance_map *instance_map_arg)
Command::~Command()
{}
-#ifdef __GNUC__
-FIX_GCC_LINKING_PROBLEM
-#endif
diff --git a/sql-common/client.c b/sql-common/client.c
index 59e27e4090a..4cbdb4b8e0d 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -864,6 +864,8 @@ mysql_free_result(MYSQL_RES *result)
{
(*mysql->methods->flush_use_result)(mysql);
mysql->status=MYSQL_STATUS_READY;
+ if (mysql->unbuffered_fetch_owner)
+ *mysql->unbuffered_fetch_owner= TRUE;
}
}
free_rows(result->data);
diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h
index e2c40c880a4..c68462be1ab 100644
--- a/sql/examples/ha_archive.h
+++ b/sql/examples/ha_archive.h
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/examples/ha_example.h b/sql/examples/ha_example.h
index 3c6ce4220ee..ae72e5bb275 100644
--- a/sql/examples/ha_example.h
+++ b/sql/examples/ha_example.h
@@ -21,7 +21,7 @@
that you can implement.
*/
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/field.cc b/sql/field.cc
index 00f729d5b07..34c5210b43c 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2229,12 +2229,6 @@ void Field_decimal::sql_type(String &res) const
** Field_new_decimal
****************************************************************************/
-/*
- Constructors of new decimal field. In case of using NOT_FIXED_DEC it try
- to use maximally allowed length (DECIMAL_MAX_LENGTH) and number of digits
- after decimal point maximally close to half of this range
- (min(DECIMAL_MAX_LENGTH/2, NOT_FIXED_DEC-1))
-*/
Field_new_decimal::Field_new_decimal(char *ptr_arg,
uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -2243,17 +2237,15 @@ Field_new_decimal::Field_new_decimal(char *ptr_arg,
struct st_table *table_arg,
uint8 dec_arg,bool zero_arg,
bool unsigned_arg)
- :Field_num(ptr_arg,
- (dec_arg == NOT_FIXED_DEC || len_arg > DECIMAL_MAX_LENGTH ?
- DECIMAL_MAX_LENGTH : len_arg),
+ :Field_num(ptr_arg, len_arg,
null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg,
- (dec_arg == NOT_FIXED_DEC ?
- min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1) :
- dec_arg),
- zero_arg, unsigned_arg)
+ dec_arg, zero_arg, unsigned_arg)
{
- bin_size= my_decimal_get_binary_size(field_length, dec);
+ precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
+ (dec <= DECIMAL_MAX_SCALE));
+ bin_size= my_decimal_get_binary_size(precision, dec);
}
@@ -2261,18 +2253,18 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg,
bool maybe_null,
const char *name,
struct st_table *t_arg,
- uint8 dec_arg)
- :Field_num((char*) 0,
- (dec_arg == NOT_FIXED_DEC|| len_arg > DECIMAL_MAX_LENGTH ?
- DECIMAL_MAX_LENGTH : len_arg),
+ uint8 dec_arg,
+ bool unsigned_arg)
+ :Field_num((char*) 0, len_arg,
maybe_null ? (uchar*) "": 0, 0,
NONE, name, t_arg,
- (dec_arg == NOT_FIXED_DEC ?
- min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1) :
- dec_arg),
- 0, 0)
+ dec_arg,
+ 0, unsigned_arg)
{
- bin_size= my_decimal_get_binary_size(field_length, dec);
+ precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
+ (dec <= DECIMAL_MAX_SCALE));
+ bin_size= my_decimal_get_binary_size(precision, dec);
}
@@ -2295,7 +2287,7 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
bool sign)
{
DBUG_ENTER("Field_new_decimal::set_value_on_overflow");
- max_my_decimal(decimal_value, field_length, decimals());
+ max_my_decimal(decimal_value, precision, decimals());
if (sign)
{
if (unsigned_flag)
@@ -2326,10 +2318,14 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
{
- my_decimal *dec= (my_decimal*)decimal_value;
int error= 0;
DBUG_ENTER("Field_new_decimal::store_value");
- dbug_print_decimal("enter", "value: %s", dec);
+#ifndef DBUG_OFF
+ {
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value)));
+ }
+#endif
/* check that we do not try to write negative value in unsigned field */
if (unsigned_flag && decimal_value->sign())
@@ -2337,25 +2333,27 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
DBUG_PRINT("info", ("unsigned overflow"));
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
- dec= &decimal_zero;
+ decimal_value= &decimal_zero;
+ }
+#ifndef DBUG_OFF
+ {
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("info", ("saving with precision %d, scale: %d, value %s",
+ (int)precision, (int)dec,
+ dbug_decimal_as_string(dbug_buff, decimal_value)));
}
- DBUG_PRINT("info", ("saving with precision %d, scale: %d",
- (int)field_length, (int)decimals()));
- dbug_print_decimal("info", "value: %s", dec);
+#endif
- if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR &
- ~E_DEC_OVERFLOW,
- dec, ptr,
- field_length,
- decimals())))
+ if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+ decimal_value, ptr, precision, dec)))
{
my_decimal buff;
DBUG_PRINT("info", ("overflow"));
- set_value_on_overflow(&buff, dec->sign());
- my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, field_length, decimals());
+ set_value_on_overflow(&buff, decimal_value->sign());
+ my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
error= 1;
}
- DBUG_EXECUTE("info", print_decimal_buff(dec, (byte *) ptr, bin_size););
+ DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr, bin_size););
DBUG_RETURN(error);
}
@@ -2387,7 +2385,11 @@ int Field_new_decimal::store(const char *from, uint length,
break;
}
- dbug_print_decimal("enter", "value: %s", &decimal_value);
+#ifndef DBUG_OFF
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("enter", ("value: %s",
+ dbug_decimal_as_string(dbug_buff, &decimal_value)));
+#endif
store_value(&decimal_value);
DBUG_RETURN(err);
}
@@ -2477,8 +2479,7 @@ my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
{
DBUG_ENTER("Field_new_decimal::val_decimal");
binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
- field_length,
- decimals());
+ precision, dec);
DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (byte *) ptr,
bin_size););
DBUG_RETURN(decimal_value);
@@ -2489,12 +2490,9 @@ String *Field_new_decimal::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
my_decimal decimal_value;
- int fixed_precision= (zerofill ?
- (field_length + (decimals() ? 1 : 0)) :
- 0);
+ uint fixed_precision= zerofill ? precision : 0;
my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
- fixed_precision, decimals(), '0',
- val_buffer);
+ fixed_precision, dec, '0', val_buffer);
return val_buffer;
}
@@ -2516,7 +2514,7 @@ void Field_new_decimal::sql_type(String &str) const
{
CHARSET_INFO *cs= str.charset();
str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
- "decimal(%d,%d)", field_length, (int)dec));
+ "decimal(%d,%d)", precision, (int)dec));
add_zerofill_and_unsigned(str);
}
@@ -7267,12 +7265,38 @@ void Field_geom::sql_type(String &res) const
}
+int Field_geom::store(double nr)
+{
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
+ return -1;
+}
+
+
+int Field_geom::store(longlong nr)
+{
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
+ return -1;
+}
+
+
+int Field_geom::store_decimal(const my_decimal *)
+{
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
+ return -1;
+}
+
+
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{
if (!length)
bzero(ptr, Field_blob::pack_length());
else
{
+ if (from == Geometry::bad_geometry_data.ptr())
+ goto err;
// Check given WKB
uint32 wkb_type;
if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
@@ -7280,7 +7304,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
wkb_type= uint4korr(from + WKB_HEADER_SIZE);
if (wkb_type < (uint32) Geometry::wkb_point ||
wkb_type > (uint32) Geometry::wkb_end)
- return -1;
+ goto err;
Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
{ // Must make a copy
@@ -7293,6 +7317,8 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
err:
bzero(ptr, Field_blob::pack_length());
+ my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
+ ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
return -1;
}
@@ -8034,7 +8060,12 @@ void create_field::create_length_to_internal_length(void)
}
break;
case MYSQL_TYPE_NEWDECIMAL:
- key_length= pack_length= my_decimal_get_binary_size(length, decimals);
+ key_length= pack_length=
+ my_decimal_get_binary_size(my_decimal_length_to_precision(length,
+ decimals,
+ flags &
+ UNSIGNED_FLAG),
+ decimals);
break;
default:
key_length= pack_length= calc_pack_length(sql_type, length);
diff --git a/sql/field.h b/sql/field.h
index 22787850442..f68a2327dff 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -20,7 +20,7 @@
variables must declare the size_of() member function.
*/
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -118,6 +118,7 @@ public:
String *val_int_as_str(String *val_buffer, my_bool unsigned_flag);
virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); }
+ virtual Item_result cast_to_int_type () const { return result_type(); }
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
static Item_result result_merge_type(enum_field_types);
bool eq(Field *field)
@@ -197,7 +198,7 @@ public:
virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
- virtual void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
+ inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
}
@@ -299,8 +300,6 @@ public:
int warn_if_overflow(int op_result);
/* maximum possible display length */
virtual uint32 max_length()= 0;
- /* length of field value symbolic representation (in bytes) */
- virtual uint32 representation_length() { return field_length; }
/* convert decimal to longlong with overflow check */
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
int *err);
@@ -437,7 +436,13 @@ public:
/* New decimal/numeric field which use fixed point arithmetic */
class Field_new_decimal :public Field_num {
public:
+ /* The maximum number of decimal digits can be stored */
+ uint precision;
uint bin_size;
+ /* Constructors take max_length of the field as a parameter - not the */
+ /* precision as the number of decimal digits allowed */
+ /* So for example we need to count length from precision handling */
+ /* CREATE TABLE ( DECIMAL(x,y)) */
Field_new_decimal(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
@@ -445,7 +450,8 @@ public:
uint8 dec_arg, bool zero_arg, bool unsigned_arg);
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const char *field_name_arg,
- struct st_table *table_arg, uint8 dec_arg);
+ struct st_table *table_arg, uint8 dec_arg,
+ bool unsigned_arg);
enum_field_types type() const { return FIELD_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
@@ -464,10 +470,7 @@ public:
void sort_string(char *buff, uint length);
bool zero_pack() const { return 0; }
void sql_type(String &str) const;
- uint32 max_length()
- { return field_length + 1 + (dec ? 1 : 0) + (field_length == dec ? 1 : 0); }
- uint32 representation_length()
- { return field_length + 1 + (dec ? 1 : 0) + (field_length == dec ? 1 : 0); };
+ uint32 max_length() { return field_length; }
uint size_of() const { return sizeof(*this); }
uint32 pack_length() const { return (uint32) bin_size; }
};
@@ -1189,9 +1192,9 @@ public:
enum_field_types type() const { return FIELD_TYPE_GEOMETRY; }
void sql_type(String &str) const;
int store(const char *to, uint length, CHARSET_INFO *charset);
- int store(double nr) { return 1; }
- int store(longlong nr) { return 1; }
- int store_decimal(const my_decimal *) { return 1; }
+ int store(double nr);
+ int store(longlong nr);
+ int store_decimal(const my_decimal *);
void get_key_image(char *buff,uint length,imagetype type);
};
#endif /*HAVE_SPATIAL*/
@@ -1216,6 +1219,7 @@ public:
}
enum_field_types type() const { return FIELD_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
+ enum Item_result cast_to_int_type () const { return INT_RESULT; }
enum ha_base_keytype key_type() const;
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 04d81b2f95a..725674946ee 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -2012,9 +2012,7 @@ THR_LOCK_DATA **ha_berkeley::store_lock(THD *thd, THR_LOCK_DATA **to,
lock_type <= TL_WRITE) &&
!thd->in_lock_tables)
lock_type = TL_WRITE_ALLOW_WRITE;
- lock.type=lock_type;
- lock_on_read= ((table->reginfo.lock_type > TL_WRITE_ALLOW_READ) ? DB_RMW :
- 0);
+ lock.type= lock_type;
}
*to++= &lock;
return to;
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 10e61455867..f6376939445 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -57,7 +57,6 @@ class ha_berkeley: public handler
ulong alloced_rec_buff_length;
ulong changed_rows;
uint primary_key,last_dup_key, hidden_primary_key, version;
- u_int32_t lock_on_read;
bool key_read, using_ignore;
bool fix_rec_buff_for_blob(ulong length);
byte current_ident[BDB_HIDDEN_PRIMARY_KEY_LENGTH];
diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc
index d9aedbe751d..c5062c4ea81 100644
--- a/sql/ha_blackhole.cc
+++ b/sql/ha_blackhole.cc
@@ -19,13 +19,13 @@
#pragma implementation // gcc: Class implementation
#endif
-#include <mysql_priv.h>
+#include "mysql_priv.h"
#ifdef HAVE_BLACKHOLE_DB
#include "ha_blackhole.h"
-static const char *ha_black_hole_exts[] = {
+static const char *ha_blackhole_exts[] = {
NullS
};
diff --git a/sql/ha_blackhole.h b/sql/ha_blackhole.h
index b6f924e94b9..84a386e17f8 100644
--- a/sql/ha_blackhole.h
+++ b/sql/ha_blackhole.h
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 52ff776c5d6..e3212b095cf 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -424,7 +424,8 @@ THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
int ha_heap::delete_table(const char *name)
{
char buff[FN_REFLEN];
- int error= heap_delete_table(fn_format(buff,name,"","",4+2));
+ int error= heap_delete_table(fn_format(buff,name,"","",
+ MY_REPLACE_EXT|MY_UNPACK_FILENAME));
return error == ENOENT ? 0 : error;
}
@@ -555,7 +556,8 @@ int ha_heap::create(const char *name, TABLE *table_arg,
hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
hp_create_info.with_auto_increment= found_real_auto_increment;
max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row);
- error= heap_create(fn_format(buff,name,"","",4+2),
+ error= heap_create(fn_format(buff,name,"","",
+ MY_REPLACE_EXT|MY_UNPACK_FILENAME),
keys, keydef, share->reclength,
(ulong) ((share->max_rows < max_rows &&
share->max_rows) ?
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index fb526888b01..5d50270ec5b 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 4217b694f06..196c60764c5 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1805,7 +1805,7 @@ try_again:
goto try_again;
}
-#endif HAVE_REPLICATION
+#endif // HAVE_REPLICATION
return(0);
}
@@ -1904,6 +1904,8 @@ innobase_repl_report_sent_binlog(
pthread_cond_broadcast(&innobase_repl_cond);
}
+
+ return(0);
}
#endif /* HAVE_REPLICATION */
@@ -2450,18 +2452,6 @@ set_field_in_record_to_null(
record[null_offset] = record[null_offset] | field->null_bit;
}
-/******************************************************************
-Resets SQL NULL bits in a record to zero. */
-inline
-void
-reset_null_bits(
-/*============*/
- TABLE* table, /* in: MySQL table object */
- char* record) /* in: a row in MySQL format */
-{
- bzero(record, table->s->null_bytes);
-}
-
extern "C" {
/*****************************************************************
InnoDB uses this function to compare two data fields for which the data type
@@ -6144,10 +6134,12 @@ innodb_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
{
- Protocol *protocol= thd->protocol;
- trx_t* trx;
- long flen;
- char* str;
+ Protocol* protocol = thd->protocol;
+ trx_t* trx;
+ static const char truncated_msg[] = "... truncated...\n";
+ const long MAX_STATUS_SIZE = 64000;
+ ulint trx_list_start = ULINT_UNDEFINED;
+ ulint trx_list_end = ULINT_UNDEFINED;
DBUG_ENTER("innodb_show_status");
@@ -6162,32 +6154,58 @@ innodb_show_status(
innobase_release_stat_resources(trx);
- /* We let the InnoDB Monitor to output at most 64000 bytes of text. */
+ /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
+ bytes of text. */
+
+ long flen, usable_len;
+ char* str;
mutex_enter_noninline(&srv_monitor_file_mutex);
rewind(srv_monitor_file);
-
- srv_printf_innodb_monitor(srv_monitor_file);
+ srv_printf_innodb_monitor(srv_monitor_file,
+ &trx_list_start, &trx_list_end);
flen = ftell(srv_monitor_file);
os_file_set_eof(srv_monitor_file);
if (flen < 0) {
flen = 0;
- } else if (flen > 64000 - 1) {
- flen = 64000 - 1;
+ }
+
+ if (flen > MAX_STATUS_SIZE) {
+ usable_len = MAX_STATUS_SIZE;
+ } else {
+ usable_len = flen;
}
/* allocate buffer for the string, and
read the contents of the temporary file */
- if (!(str = my_malloc(flen + 1, MYF(0)))) {
- mutex_exit_noninline(&srv_monitor_file_mutex);
-
- DBUG_RETURN(TRUE);
+ if (!(str = my_malloc(usable_len + 1, MYF(0))))
+ {
+ mutex_exit_noninline(&srv_monitor_file_mutex);
+ DBUG_RETURN(TRUE);
}
rewind(srv_monitor_file);
- flen = fread(str, 1, flen, srv_monitor_file);
+ if (flen < MAX_STATUS_SIZE) {
+ /* Display the entire output. */
+ flen = fread(str, 1, flen, srv_monitor_file);
+ } else if (trx_list_end < (ulint) flen
+ && trx_list_start < trx_list_end
+ && trx_list_start + (flen - trx_list_end)
+ < MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
+ /* Omit the beginning of the list of active transactions. */
+ long len = fread(str, 1, trx_list_start, srv_monitor_file);
+ memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
+ len += sizeof truncated_msg - 1;
+ usable_len = (MAX_STATUS_SIZE - 1) - len;
+ fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
+ len += fread(str + len, 1, usable_len, srv_monitor_file);
+ flen = len;
+ } else {
+ /* Omit the end of the output. */
+ flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
+ }
mutex_exit_noninline(&srv_monitor_file_mutex);
@@ -6427,15 +6445,15 @@ ha_innobase::store_lock(
(lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
thd->lex->sql_command != SQLCOM_SELECT &&
thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
- thd->lex->sql_command != SQLCOM_DELETE_MULTI ) {
+ thd->lex->sql_command != SQLCOM_DELETE_MULTI &&
+ thd->lex->sql_command != SQLCOM_LOCK_TABLES) {
/* In case we have innobase_locks_unsafe_for_binlog
option set and isolation level of the transaction
is not set to serializable and MySQL is doing
- INSERT INTO...SELECT without FOR UPDATE or IN
- SHARE MODE we use consistent read for select.
- Similarly, in case of DELETE...SELECT and
- UPDATE...SELECT when these are not multi table.*/
+ INSERT INTO...SELECT or UPDATE ... = (SELECT ...)
+ without FOR UPDATE or IN SHARE MODE in select, then
+ we use consistent read for select. */
prebuilt->select_lock_type = LOCK_NONE;
prebuilt->stored_select_lock_type = LOCK_NONE;
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 6c412a889b2..bcbc38650b3 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -21,7 +21,7 @@
Innodb
*/
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 7e14a3b7941..bbd9721f8e2 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 5add9478bf4..f7c0abf9810 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -400,6 +400,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
const char **table_names, **pos;
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
THD *thd= current_thd;
+ uint dirlgt= dirname_length(name);
DBUG_ENTER("ha_myisammrg::create");
if (!(table_names= (const char**)
@@ -413,11 +414,30 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
tbl= find_temporary_table(thd, tables->db, tables->table_name);
if (!tbl)
{
- uint length= my_snprintf(buff,FN_REFLEN,"%s%s/%s",
- mysql_real_data_home,
+ /*
+ Construct the path to the MyISAM table. Try to meet two conditions:
+ 1.) Allow to include MyISAM tables from different databases, and
+ 2.) allow for moving DATADIR around in the file system.
+ The first means that we need paths in the .MRG file. The second
+ means that we should not have absolute paths in the .MRG file.
+ The best, we can do, is to use 'mysql_data_home', which is '.'
+ in mysqld and may be an absolute path in an embedded server.
+ This means that it might not be possible to move the DATADIR of
+ an embedded server without changing the paths in the .MRG file.
+ */
+ uint length= my_snprintf(buff, FN_REFLEN, "%s/%s/%s", mysql_data_home,
tables->db, tables->table_name);
- if (!(table_name= thd->strmake(buff, length)))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ /*
+ If a MyISAM table is in the same directory as the MERGE table,
+ we use the table name without a path. This means that the
+ DATADIR can easily be moved even for an embedded server as long
+ as the MyISAM tables are from the same database as the MERGE table.
+ */
+ if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt))
+ table_name= tables->table_name;
+ else
+ if (! (table_name= thd->strmake(buff, length)))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
else
table_name= (*tbl)->s->path;
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index 6058c32c805..3bc9c11d4be 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index b61dbd1792c..372a178b59a 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1,4 +1,4 @@
- /* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1227,7 +1227,7 @@ static void shrink_varchar(Field* field, const byte* & ptr, char* buf)
if (ptr[1] == 0) {
buf[0]= ptr[0];
} else {
- DBUG_ASSERT(false);
+ DBUG_ASSERT(FALSE);
buf[0]= 255;
}
memmove(buf + 1, ptr + 2, pack_len - 1);
@@ -1773,7 +1773,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
if (p.bound_type == -1)
{
DBUG_PRINT("error", ("key %d unknown flag %d", j, p.key->flag));
- DBUG_ASSERT(false);
+ DBUG_ASSERT(FALSE);
// Stop setting bounds but continue with what we have
op->end_of_bound(range_no);
DBUG_RETURN(0);
@@ -1850,7 +1850,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
if (m_active_cursor == 0)
{
- restart= false;
+ restart= FALSE;
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
@@ -1860,7 +1860,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
ERR_RETURN(trans->getNdbError());
m_active_cursor= op;
} else {
- restart= true;
+ restart= TRUE;
op= (NdbIndexScanOperation*)m_active_cursor;
DBUG_ASSERT(op->getSorted() == sorted);
@@ -2741,7 +2741,7 @@ int ha_ndbcluster::close_scan()
m_ops_pending= 0;
}
- cursor->close(m_force_send, true);
+ cursor->close(m_force_send, TRUE);
m_active_cursor= m_multi_cursor= NULL;
DBUG_RETURN(0);
}
@@ -3050,8 +3050,10 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows)
m_rows_inserted= (ha_rows) 0;
if (rows == (ha_rows) 0)
+ {
/* We don't know how many will be inserted, guess */
m_rows_to_insert= m_autoincrement_prefetch;
+ }
else
m_rows_to_insert= rows;
@@ -3621,7 +3623,7 @@ static int create_ndb_column(NDBCOL &col,
case MYSQL_TYPE_NEWDECIMAL:
{
Field_new_decimal *f= (Field_new_decimal*)field;
- uint precision= f->field_length;
+ uint precision= f->precision;
uint scale= f->decimals();
if (field->flags & UNSIGNED_FLAG)
{
@@ -4174,8 +4176,10 @@ ulonglong ha_ndbcluster::get_auto_increment()
Ndb *ndb= get_ndb();
if (m_rows_inserted > m_rows_to_insert)
+ {
/* We guessed too low */
m_rows_to_insert+= m_autoincrement_prefetch;
+ }
cache_size=
(int)
(m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ?
@@ -5554,7 +5558,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
/**
* blobs can't be batched currently
*/
- m_disable_multi_read= true;
+ m_disable_multi_read= TRUE;
DBUG_RETURN(handler::read_multi_range_first(found_range_p,
ranges,
range_count,
@@ -5562,7 +5566,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
buffer));
}
- m_disable_multi_read= false;
+ m_disable_multi_read= FALSE;
/**
* Copy arguments into member variables
@@ -5610,7 +5614,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
!op->readTuple(lm) &&
!set_primary_key(op, multi_range_curr->start_key.key) &&
!define_read_attrs(curr, op) &&
- (op->setAbortOption(AO_IgnoreError), true))
+ (op->setAbortOption(AO_IgnoreError), TRUE))
curr += reclength;
else
ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
@@ -5625,7 +5629,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
!op->readTuple(lm) &&
!set_index_key(op, key_info, multi_range_curr->start_key.key) &&
!define_read_attrs(curr, op) &&
- (op->setAbortOption(AO_IgnoreError), true))
+ (op->setAbortOption(AO_IgnoreError), TRUE))
curr += reclength;
else
ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
@@ -5660,7 +5664,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
end_of_buffer -= reclength;
}
else if ((scanOp= m_active_trans->getNdbIndexScanOperation(idx, tab))
- &&!scanOp->readTuples(lm, 0, parallelism, sorted, false, true)
+ &&!scanOp->readTuples(lm, 0, parallelism, sorted, FALSE, TRUE)
&&!generate_scan_filter(m_cond_stack, scanOp)
&&!define_read_attrs(end_of_buffer-reclength, scanOp))
{
@@ -5807,11 +5811,11 @@ ha_ndbcluster::read_multi_range_next(KEY_MULTI_RANGE ** multi_range_found_p)
continue;
}
- DBUG_ASSERT(false); // Should only get here via goto's
+ DBUG_ASSERT(FALSE); // Should only get here via goto's
close_scan:
if (res == 1)
{
- m_multi_cursor->close(false, true);
+ m_multi_cursor->close(FALSE, TRUE);
m_active_cursor= m_multi_cursor= 0;
DBUG_MULTI_RANGE(8);
continue;
@@ -6101,8 +6105,8 @@ const
COND*
ha_ndbcluster::cond_push(const COND *cond)
{
- Ndb_cond_stack *ndb_cond = new Ndb_cond_stack();
DBUG_ENTER("cond_push");
+ Ndb_cond_stack *ndb_cond = new Ndb_cond_stack();
DBUG_EXECUTE("where",print_where((COND *)cond, m_tabname););
if (m_cond_stack)
ndb_cond->next= m_cond_stack;
@@ -6118,7 +6122,6 @@ ha_ndbcluster::cond_push(const COND *cond)
{
cond_pop();
}
-
DBUG_RETURN(cond);
}
@@ -6997,7 +7000,7 @@ int
ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter)
{
uint level=0;
- bool negated= false;
+ bool negated= FALSE;
DBUG_ENTER("build_scan_filter_group");
do
@@ -7013,7 +7016,7 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter)
if ((negated) ? filter->begin(NdbScanFilter::NAND)
: filter->begin(NdbScanFilter::AND) == -1)
DBUG_RETURN(1);
- negated= false;
+ negated= FALSE;
cond= cond->next;
break;
}
@@ -7024,19 +7027,19 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter)
if ((negated) ? filter->begin(NdbScanFilter::NOR)
: filter->begin(NdbScanFilter::OR) == -1)
DBUG_RETURN(1);
- negated= false;
+ negated= FALSE;
cond= cond->next;
break;
}
case(Item_func::NOT_FUNC): {
cond= cond->next;
- negated= true;
+ negated= TRUE;
break;
}
default:
if (build_scan_filter_predicate(cond, filter, negated))
DBUG_RETURN(1);
- negated= false;
+ negated= FALSE;
break;
}
break;
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 81b2873d9dd..8012f16e42e 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -21,7 +21,7 @@
/* The class defining a handle to an NDB Cluster table */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/handler.cc b/sql/handler.cc
index d2501afe97a..a34b3bd8aac 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -185,9 +185,10 @@ enum db_type ha_checktype(enum db_type database_type)
thd= current_thd;
return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
(enum db_type) thd->variables.table_type :
- (enum db_type) global_system_variables.table_type !=
- DB_TYPE_UNKNOWN ?
- (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM);
+ ((enum db_type) global_system_variables.table_type !=
+ DB_TYPE_UNKNOWN ?
+ (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM)
+ );
} /* ha_checktype */
@@ -365,11 +366,11 @@ int ha_init()
if (opt_bin_log)
{
- if (!(*ht= binlog_init()))
+ if (!(*ht= binlog_init())) // Always succeed
{
- mysql_bin_log.close(LOG_CLOSE_INDEX);
- opt_bin_log= 0;
- error= 1;
+ mysql_bin_log.close(LOG_CLOSE_INDEX); // Never used
+ opt_bin_log= 0; // Never used
+ error= 1; // Never used
}
else
ha_was_inited_ok(ht++);
@@ -2416,6 +2417,7 @@ TYPELIB *ha_known_exts(void)
return &known_extensions;
}
+
#ifdef HAVE_REPLICATION
/*
Reports to table handlers up to which position we have sent the binlog
@@ -2423,19 +2425,16 @@ TYPELIB *ha_known_exts(void)
SYNOPSIS
ha_repl_report_sent_binlog()
+ thd thread doing the binlog communication to the slave
+ log_file_name binlog file name
+ end_offse t the offset in the binlog file up to which we sent the
+ contents to the slave
NOTES
Only works for InnoDB at the moment
RETURN VALUE
Always 0 (= success)
-
- PARAMETERS
- THD *thd in: thread doing the binlog communication to
- the slave
- char *log_file_name in: binlog file name
- my_off_t end_offset in: the offset in the binlog file up to
- which we sent the contents to the slave
*/
int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
@@ -2444,17 +2443,17 @@ int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
#ifdef HAVE_INNOBASE_DB
return innobase_repl_report_sent_binlog(thd,log_file_name,end_offset);
#else
- /* remove warnings about unused parameters */
- thd=thd; log_file_name=log_file_name; end_offset=end_offset;
return 0;
#endif
}
+
/*
Reports to table handlers that we stop replication to a specific slave
SYNOPSIS
ha_repl_report_replication_stop()
+ thd thread doing the binlog communication to the slave
NOTES
Does nothing at the moment
@@ -2463,14 +2462,10 @@ int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
Always 0 (= success)
PARAMETERS
- THD *thd in: thread doing the binlog communication to
- the slave
*/
int ha_repl_report_replication_stop(THD *thd)
{
- thd = thd;
-
return 0;
}
#endif /* HAVE_REPLICATION */
diff --git a/sql/handler.h b/sql/handler.h
index 5e25f038c36..11f8dd0b4d7 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -17,7 +17,7 @@
/* Definitions for parameters to do with handler-routines */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/hostname.cc b/sql/hostname.cc
index c74d230bbcb..ec5c6f29a27 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -177,7 +177,14 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
&tmp_errno)))
{
DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno));
- add_wrong_ip(in);
+ /*
+ Don't cache responses when the DSN server is down, as otherwise
+ transient DNS failure may leave any number of clients (those
+ that attempted to connect during the outage) unable to connect
+ indefinitely.
+ */
+ if (tmp_errno == HOST_NOT_FOUND || tmp_errno == NO_DATA)
+ add_wrong_ip(in);
my_gethostbyname_r_free();
DBUG_RETURN(0);
}
@@ -200,13 +207,17 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
{
VOID(pthread_mutex_unlock(&LOCK_hostname));
DBUG_PRINT("error",("gethostbyaddr returned %d",errno));
- goto err;
+
+ if (errno == HOST_NOT_FOUND || errno == NO_DATA)
+ add_wrong_ip(in); /* only cache negative responses, not failures */
+
+ DBUG_RETURN(0);
}
if (!hp->h_name[0]) // Don't allow empty hostnames
{
VOID(pthread_mutex_unlock(&LOCK_hostname));
DBUG_PRINT("error",("Got an empty hostname"));
- goto err;
+ goto add_wrong_ip_and_return;
}
if (!(name=my_strdup(hp->h_name,MYF(0))))
{
@@ -233,7 +244,7 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
{
DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'"));
my_free(name,MYF(0));
- goto err;
+ goto add_wrong_ip_and_return;
}
}
@@ -249,7 +260,7 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname"));
my_free(name,MYF(0));
-err:
+add_wrong_ip_and_return:
add_wrong_ip(in);
DBUG_RETURN(0);
}
diff --git a/sql/item.cc b/sql/item.cc
index 7264f8b2d68..8100e78491b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -80,7 +80,7 @@ Hybrid_type_traits_decimal::fix_length_and_dec(Item *item, Item *arg) const
{
item->decimals= arg->decimals;
item->max_length= min(arg->max_length + DECIMAL_LONGLONG_DIGITS,
- DECIMAL_MAX_LENGTH);
+ DECIMAL_MAX_STR_LENGTH);
}
@@ -348,6 +348,17 @@ Item::Item(THD *thd, Item *item):
}
+uint Item::decimal_precision() const
+{
+ Item_result restype= result_type();
+
+ if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
+ return min(my_decimal_length_to_precision(max_length, decimals, unsigned_flag),
+ DECIMAL_MAX_PRECISION);
+ return min(max_length, DECIMAL_MAX_PRECISION);
+}
+
+
void Item::print_item_w_name(String *str)
{
print(str);
@@ -454,6 +465,7 @@ void Item_ident::cleanup()
db_name= orig_db_name;
table_name= orig_table_name;
field_name= orig_field_name;
+ depended_from= 0;
DBUG_VOID_RETURN;
}
@@ -498,10 +510,10 @@ bool Item_field::collect_item_field_processor(byte *arg)
while ((curr_item= item_list_it++))
{
if (curr_item->eq(this, 1))
- DBUG_RETURN(false); /* Already in the set. */
+ DBUG_RETURN(FALSE); /* Already in the set. */
}
item_list->push_back(this);
- DBUG_RETURN(false);
+ DBUG_RETURN(FALSE);
}
@@ -557,6 +569,11 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
bool Item::eq(const Item *item, bool binary_cmp) const
{
+ /*
+ Note, that this is never TRUE if item is a Item_param:
+ for all basic constants we have special checks, and Item_param's
+ type() can be only among basic constant types.
+ */
return type() == item->type() && name && item->name &&
!my_strcasecmp(system_charset_info,name,item->name);
}
@@ -601,7 +618,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
bool Item_string::eq(const Item *item, bool binary_cmp) const
{
- if (type() == item->type())
+ if (type() == item->type() && item->basic_const_item())
{
if (binary_cmp)
return !stringcmp(&str_value, &item->str_value);
@@ -723,6 +740,13 @@ Item_splocal::this_item()
return thd->spcont->get_item(m_offset);
}
+
+Item **
+Item_splocal::this_item_addr(THD *thd, Item **addr)
+{
+ return thd->spcont->get_item_addr(m_offset);
+}
+
Item *
Item_splocal::this_const_item() const
{
@@ -937,10 +961,8 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
return 1;
}
if (collation->state & MY_CS_BINSORT)
- {
return 0;
- }
- else if (dt.collation->state & MY_CS_BINSORT)
+ if (dt.collation->state & MY_CS_BINSORT)
{
set(dt);
return 0;
@@ -1020,7 +1042,7 @@ void Item_field::set_field(Field *field_par)
field=result_field=field_par; // for easy coding with fields
maybe_null=field->maybe_null();
decimals= field->decimals();
- max_length= field_par->representation_length();
+ max_length= field_par->max_length();
table_name= *field_par->table_name;
field_name= field_par->field_name;
db_name= field_par->table->s->db;
@@ -1335,6 +1357,13 @@ Item_uint::Item_uint(const char *str_arg, uint length):
}
+Item_uint::Item_uint(const char *str_arg, longlong i, uint length):
+ Item_int(str_arg, i, length)
+{
+ unsigned_flag= 1;
+}
+
+
String *Item_uint::val_str(String *str)
{
// following assert is redundant, because fixed=1 assigned in constructor
@@ -1358,18 +1387,18 @@ Item_decimal::Item_decimal(const char *str_arg, uint length,
str2my_decimal(E_DEC_FATAL_ERROR, str_arg, length, charset, &decimal_value);
name= (char*) str_arg;
decimals= (uint8) decimal_value.frac;
- max_length= my_decimal_max_length(&decimal_value);
fixed= 1;
- unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
}
Item_decimal::Item_decimal(longlong val, bool unsig)
{
int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value);
decimals= (uint8) decimal_value.frac;
- max_length= my_decimal_max_length(&decimal_value);
fixed= 1;
- unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
}
@@ -1377,9 +1406,9 @@ Item_decimal::Item_decimal(double val, int precision, int scale)
{
double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value);
decimals= (uint8) decimal_value.frac;
- max_length= my_decimal_max_length(&decimal_value);
fixed= 1;
- unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
}
@@ -1391,7 +1420,6 @@ Item_decimal::Item_decimal(const char *str, const my_decimal *val_arg,
decimals= (uint8) decimal_par;
max_length= length;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
}
@@ -1399,19 +1427,20 @@ Item_decimal::Item_decimal(my_decimal *value_par)
{
my_decimal2decimal(value_par, &decimal_value);
decimals= (uint8) decimal_value.frac;
- max_length= my_decimal_max_length(value_par);
fixed= 1;
- unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, !decimal_value.sign());
}
Item_decimal::Item_decimal(const char *bin, int precision, int scale)
{
- binary2my_decimal(E_DEC_FATAL_ERROR, bin, &decimal_value, precision, scale);
+ binary2my_decimal(E_DEC_FATAL_ERROR, bin,
+ &decimal_value, precision, scale);
decimals= (uint8) decimal_value.frac;
- max_length= my_decimal_max_length(&decimal_value);
fixed= 1;
- unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ !decimal_value.sign());
}
@@ -1443,6 +1472,24 @@ void Item_decimal::print(String *str)
}
+bool Item_decimal::eq(const Item *item, bool binary_cmp) const
+{
+ if (type() == item->type() && item->basic_const_item())
+ {
+ /*
+ We need to cast off const to call val_decimal(). This should
+ be OK for a basic constant. Additionally, we can pass 0 as
+ a true decimal constant will return its internal decimal
+ storage and ignore the argument.
+ */
+ Item *arg= (Item*) item;
+ my_decimal *value= arg->val_decimal(0);
+ return !my_decimal_cmp(&decimal_value, value);
+ }
+ return 0;
+}
+
+
String *Item_float::val_str(String *str)
{
// following assert is redundant, because fixed=1 assigned in constructor
@@ -1671,7 +1718,8 @@ void Item_param::set_decimal(const char *str, ulong length)
str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end);
state= DECIMAL_VALUE;
decimals= decimal_value.frac;
- max_length= decimal_value.intg + decimals + 2;
+ max_length= my_decimal_precision_to_length(decimal_value.precision(),
+ decimals, unsigned_flag);
maybe_null= 0;
DBUG_VOID_RETURN;
}
@@ -1822,7 +1870,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
my_decimal2decimal(ent_value, &decimal_value);
state= DECIMAL_VALUE;
decimals= ent_value->frac;
- max_length= ent_value->intg + decimals + 2;
+ max_length= my_decimal_precision_to_length(ent_value->precision(),
+ decimals, unsigned_flag);
break;
}
default:
@@ -2194,6 +2243,74 @@ bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
+bool Item_param::basic_const_item() const
+{
+ if (state == NO_VALUE || state == TIME_VALUE)
+ return FALSE;
+ return TRUE;
+}
+
+
+Item *
+Item_param::new_item()
+{
+ /* see comments in the header file */
+ switch (state) {
+ case NULL_VALUE:
+ return new Item_null(name);
+ case INT_VALUE:
+ return (unsigned_flag ?
+ new Item_uint(name, value.integer, max_length) :
+ new Item_int(name, value.integer, max_length));
+ case REAL_VALUE:
+ return new Item_float(name, value.real, decimals, max_length);
+ case STRING_VALUE:
+ case LONG_DATA_VALUE:
+ return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
+ str_value.charset());
+ case TIME_VALUE:
+ break;
+ case NO_VALUE:
+ default:
+ DBUG_ASSERT(0);
+ };
+ return 0;
+}
+
+
+bool
+Item_param::eq(const Item *arg, bool binary_cmp) const
+{
+ Item *item;
+ if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
+ return FALSE;
+ /*
+ We need to cast off const to call val_int(). This should be OK for
+ a basic constant.
+ */
+ item= (Item*) arg;
+
+ switch (state) {
+ case NULL_VALUE:
+ return TRUE;
+ case INT_VALUE:
+ return value.integer == item->val_int() &&
+ unsigned_flag == item->unsigned_flag;
+ case REAL_VALUE:
+ return value.real == item->val_real();
+ case STRING_VALUE:
+ case LONG_DATA_VALUE:
+ if (binary_cmp)
+ return !stringcmp(&str_value, &item->str_value);
+ return !sortcmp(&str_value, &item->str_value, collation.collation);
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/* End of Item_param related */
+
void Item_param::print(String *str)
{
if (state == NO_VALUE)
@@ -2334,7 +2451,7 @@ bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
*/
static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
- Item_ident *resolved_item,
+ Item_ident *resolved_item,
Item_ident *mark_item)
{
const char *db_name= (resolved_item->db_name ?
@@ -2359,6 +2476,71 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
}
+/*
+ Mark range of selects and resolved identifier (field/reference) item as
+ dependent
+
+ SYNOPSIS
+ mark_select_range_as_dependent()
+ thd - thread handler
+ last_select - select where resolved_item was resolved
+ current_sel - current select (select where resolved_item was placed)
+ found_field - field which was found during resolving
+ found_item - Item which was found during resolving (if resolved
+ identifier belongs to VIEW)
+ resolved_item - Identifier which was resolved
+
+ NOTE:
+ We have to mark all items between current_sel (including) and
+ last_select (excluding) as dependend (select before last_select should
+ be marked with actual table mask used by resolved item, all other with
+ OUTER_REF_TABLE_BIT) and also write dependence information to Item of
+ resolved identifier.
+*/
+
+void mark_select_range_as_dependent(THD *thd,
+ SELECT_LEX *last_select,
+ SELECT_LEX *current_sel,
+ Field *found_field, Item *found_item,
+ Item_ident *resolved_item)
+{
+ /*
+ Go from current SELECT to SELECT where field was resolved (it
+ have to be reachable from current SELECT, because it was already
+ done once when we resolved this field and cached result of
+ resolving)
+ */
+ SELECT_LEX *previous_select= current_sel;
+ for(;
+ previous_select->outer_select() != last_select;
+ previous_select= previous_select->outer_select())
+ {
+ Item_subselect *prev_subselect_item=
+ previous_select->master_unit()->item;
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
+ }
+ {
+ Item_subselect *prev_subselect_item=
+ previous_select->master_unit()->item;
+ Item_ident *dependent= resolved_item;
+ if (found_field == view_ref_found)
+ {
+ Item::Type type= found_item->type();
+ prev_subselect_item->used_tables_cache|=
+ found_item->used_tables();
+ dependent= ((type == Item::REF_ITEM || type == Item::FIELD_ITEM) ?
+ (Item_ident*) found_item :
+ 0);
+ }
+ else
+ prev_subselect_item->used_tables_cache|=
+ found_field->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ mark_as_dependent(thd, last_select, current_sel, resolved_item,
+ dependent);
+ }
+}
/*
@@ -3107,11 +3289,8 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
- return new Field_decimal((char*) 0, max_length, null_ptr, 0, Field::NONE,
- name, table, decimals, 0, unsigned_flag);
case MYSQL_TYPE_NEWDECIMAL:
- return new Field_new_decimal((char*) 0, max_length - (decimals?1:0),
- null_ptr, 0,
+ return new Field_new_decimal((char*) 0, max_length, null_ptr, 0,
Field::NONE, name, table, decimals, 0,
unsigned_flag);
case MYSQL_TYPE_TINY:
@@ -3346,6 +3525,35 @@ int Item_decimal::save_in_field(Field *field, bool no_conversions)
}
+bool Item_int::eq(const Item *arg, bool binary_cmp) const
+{
+ /* No need to check for null value as basic constant can't be NULL */
+ if (arg->basic_const_item() && arg->type() == type())
+ {
+ /*
+ We need to cast off const to call val_int(). This should be OK for
+ a basic constant.
+ */
+ Item *item= (Item*) arg;
+ return item->val_int() == value && item->unsigned_flag == unsigned_flag;
+ }
+ return FALSE;
+}
+
+
+Item *Item_int_with_ref::new_item()
+{
+ DBUG_ASSERT(ref->basic_const_item());
+ /*
+ We need to evaluate the constant to make sure it works with
+ parameter markers.
+ */
+ return (ref->unsigned_flag ?
+ new Item_uint(ref->name, ref->val_int(), ref->max_length) :
+ new Item_int(ref->name, ref->val_int(), ref->max_length));
+}
+
+
Item_num *Item_uint::neg()
{
Item_decimal *item= new Item_decimal(value, 0);
@@ -3433,6 +3641,21 @@ void Item_float::print(String *str)
In number context this is a longlong value.
*/
+bool Item_float::eq(const Item *arg, bool binary_cmp) const
+{
+ if (arg->basic_const_item() && arg->type() == type())
+ {
+ /*
+ We need to cast off const to call val_int(). This should be OK for
+ a basic constant.
+ */
+ Item *item= (Item*) arg;
+ return item->val_real() == value;
+ }
+ return FALSE;
+}
+
+
inline uint char_val(char X)
{
return (uint) (X >= '0' && X <= '9' ? X-'0' :
@@ -3503,6 +3726,17 @@ int Item_hex_string::save_in_field(Field *field, bool no_conversions)
}
+bool Item_hex_string::eq(const Item *arg, bool binary_cmp) const
+{
+ if (arg->basic_const_item() && arg->type() == type())
+ {
+ if (binary_cmp)
+ return !stringcmp(&str_value, &arg->str_value);
+ return !sortcmp(&str_value, &arg->str_value, collation.collation);
+ }
+ return FALSE;
+}
+
/*
bin item.
In string context this is a binary string.
@@ -4812,6 +5046,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
/* fix variable decimals which always is NOT_FIXED_DEC */
if (Field::result_merge_type(fld_type) == INT_RESULT)
decimals= 0;
+ prev_decimal_int_part= item->decimal_int_part();
}
@@ -4934,18 +5169,12 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
}
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
{
- int item_length= display_length(item);
- int intp1= item_length - min(item->decimals, NOT_FIXED_DEC - 1);
- int intp2= max_length - min(decimals, NOT_FIXED_DEC - 1);
- /* can't be overflow because it work only for decimals (no strings) */
- int dec_length= max(intp1, intp2) + decimals;
- max_length= max(max_length, (uint) max(item_length, dec_length));
- /*
- we can't allow decimals to be NOT_FIXED_DEC, to prevent creation
- decimal with max precision (see Field_new_decimal constcuctor)
- */
- if (decimals >= NOT_FIXED_DEC)
- decimals= NOT_FIXED_DEC - 1;
+ decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE);
+ int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
+ + decimals, DECIMAL_MAX_PRECISION);
+ unsigned_flag&= item->unsigned_flag;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
}
else
max_length= max(max_length, display_length(item));
@@ -4966,6 +5195,9 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
}
maybe_null|= item->maybe_null;
get_full_info(item);
+
+ /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
+ prev_decimal_int_part= decimal_int_part();
DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
(int) fld_type, max_length, (uint) decimals));
DBUG_RETURN(FALSE);
diff --git a/sql/item.h b/sql/item.h
index e86c66ca6f3..0166c5e8707 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -258,7 +258,7 @@ public:
Item *next;
uint32 max_length;
uint name_length; /* Length of name */
- uint8 marker,decimals;
+ uint8 marker, decimals;
my_bool maybe_null; /* If item may be null */
my_bool null_value; /* if item is null */
my_bool unsigned_flag;
@@ -302,7 +302,8 @@ public:
{ return save_in_field(field, 1); }
virtual bool send(Protocol *protocol, String *str);
virtual bool eq(const Item *, bool binary_cmp) const;
- virtual Item_result result_type () const { return REAL_RESULT; }
+ virtual Item_result result_type() const { return REAL_RESULT; }
+ virtual Item_result cast_to_int_type() const { return result_type(); }
virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
@@ -433,7 +434,7 @@ public:
virtual table_map not_null_tables() const { return used_tables(); }
/*
Returns true if this is a simple constant item like an integer, not
- a constant expression
+ a constant expression. Used in the optimizer to propagate basic constants.
*/
virtual bool basic_const_item() const { return 0; }
/* cloning of constant items (0 if it is not const) */
@@ -441,6 +442,9 @@ public:
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
+ virtual uint decimal_precision() const;
+ inline int decimal_int_part() const
+ { return my_decimal_int_part(decimal_precision(), decimals); }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -521,8 +525,17 @@ public:
virtual Item *equal_fields_propagator(byte * arg) { return this; }
virtual Item *set_no_const_sub(byte *arg) { return this; }
virtual Item *replace_equal_field(byte * arg) { return this; }
-
- virtual Item *this_item() { return this; } /* For SPs mostly. */
+
+ /*
+ For SP local variable returns pointer to Item representing its
+ current value and pointer to current Item otherwise.
+ */
+ virtual Item *this_item() { return this; }
+ /*
+ For SP local variable returns address of pointer to Item representing its
+ current value and pointer passed via parameter otherwise.
+ */
+ virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; }
virtual Item *this_const_item() const { return const_cast<Item*>(this); } /* For SPs mostly. */
// Row emulation
@@ -569,6 +582,7 @@ public:
bool is_splocal() { return 1; } /* Needed for error checking */
Item *this_item();
+ Item **this_item_addr(THD *thd, Item **);
Item *this_const_item() const;
bool fix_fields(THD *, struct st_table_list *, Item **);
@@ -738,6 +752,10 @@ public:
{
return field->result_type();
}
+ Item_result cast_to_int_type() const
+ {
+ return field->cast_to_int_type();
+ }
enum_field_types field_type() const
{
return field->type();
@@ -909,7 +927,6 @@ public:
bool convert_str_value(THD *thd);
- Item *new_item() { return new Item_param(pos_in_query); }
/*
If value for parameter was not set we treat it as non-const
so noone will use parameters value in fix_fields still
@@ -918,12 +935,29 @@ public:
virtual table_map used_tables() const
{ return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; }
void print(String *str);
- /* parameter never equal to other parameter of other item */
- bool eq(const Item *item, bool binary_cmp) const { return 0; }
bool is_null()
{ DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; }
+ bool basic_const_item() const;
+ /*
+ This method is used to make a copy of a basic constant item when
+ propagating constants in the optimizer. The reason to create a new
+ item and not use the existing one is not precisely known (2005/04/16).
+ Probably we are trying to preserve tree structure of items, in other
+ words, avoid pointing at one item from two different nodes of the tree.
+ Return a new basic constant item if parameter value is a basic
+ constant, assert otherwise. This method is called only if
+ basic_const_item returned TRUE.
+ */
+ Item *new_item();
+ /*
+ Implement by-value equality evaluation if parameter value
+ is set and is a basic constant (integer, real or string).
+ Otherwise return FALSE.
+ */
+ bool eq(const Item *item, bool binary_cmp) const;
};
+
class Item_int :public Item_num
{
public:
@@ -932,7 +966,7 @@ public:
{ max_length=length; fixed= 1; }
#ifdef HAVE_LONG_LONG
Item_int(longlong i,uint length=21) :value(i)
- { max_length=length; fixed= 1;}
+ { max_length=length; fixed= 1; }
#endif
Item_int(const char *str_arg,longlong i,uint length) :value(i)
{ max_length=length; name=(char*) str_arg; fixed= 1; }
@@ -951,6 +985,8 @@ public:
void cleanup() {}
void print(String *str);
Item_num *neg() { value= -value; return this; }
+ uint decimal_precision() const { return (uint)(max_length - test(value < 0)); }
+ bool eq(const Item *, bool binary_cmp) const;
};
@@ -969,6 +1005,7 @@ class Item_uint :public Item_int
{
public:
Item_uint(const char *str_arg, uint length);
+ Item_uint(const char *str_arg, longlong i, uint length);
Item_uint(uint32 i) :Item_int((longlong) i, 10)
{ unsigned_flag= 1; }
double val_real()
@@ -978,6 +1015,7 @@ public:
int save_in_field(Field *field, bool no_conversions);
void print(String *str);
Item_num *neg ();
+ uint decimal_precision() const { return max_length; }
};
@@ -1017,8 +1055,11 @@ public:
unsigned_flag= !decimal_value.sign();
return this;
}
+ uint decimal_precision() const { return decimal_value.precision(); }
+ bool eq(const Item *, bool binary_cmp) const;
};
+
class Item_float :public Item_num
{
char *presentation;
@@ -1054,6 +1095,7 @@ public:
{ return new Item_float(name, value, decimals, max_length); }
Item_num *neg() { value= -value; return this; }
void print(String *str);
+ bool eq(const Item *, bool binary_cmp) const;
};
@@ -1193,6 +1235,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
// to prevent drop fixed flag (no need parent cleanup call)
void cleanup() {}
+ bool eq(const Item *item, bool binary_cmp) const;
};
@@ -1371,11 +1414,7 @@ public:
{
return ref->save_in_field(field, no_conversions);
}
- Item *new_item()
- {
- return (ref->unsigned_flag)? new Item_uint(ref->name, ref->max_length) :
- new Item_int(ref->name, ref->max_length);
- }
+ Item *new_item();
};
@@ -1779,6 +1818,9 @@ protected:
enum_field_types fld_type;
void get_full_info(Item *item);
+
+ /* It is used to count decimal precision in join_types */
+ int prev_decimal_int_part;
public:
Item_type_holder(THD*, Item*);
@@ -1795,6 +1837,12 @@ public:
static enum_field_types get_real_type(Item *);
};
+class st_select_lex;
+void mark_select_range_as_dependent(THD *thd,
+ st_select_lex *last_select,
+ st_select_lex *current_sel,
+ Field *found_field, Item *found_item,
+ Item_ident *resolved_item);
extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 66354560756..89897a9d74f 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1134,6 +1134,14 @@ Item_func_ifnull::fix_length_and_dec()
cached_field_type= Item_func::field_type();
}
+
+uint Item_func_ifnull::decimal_precision() const
+{
+ int max_int_part=max(args[0]->decimal_int_part(),args[1]->decimal_int_part());
+ return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+}
+
+
enum_field_types Item_func_ifnull::field_type() const
{
return cached_field_type;
@@ -1251,6 +1259,14 @@ Item_func_if::fix_length_and_dec()
}
+uint Item_func_if::decimal_precision() const
+{
+ int precision=(max(args[1]->decimal_int_part(),args[2]->decimal_int_part())+
+ decimals);
+ return min(precision, DECIMAL_MAX_PRECISION);
+}
+
+
double
Item_func_if::val_real()
{
@@ -1304,7 +1320,8 @@ Item_func_nullif::fix_length_and_dec()
{
max_length=args[0]->max_length;
decimals=args[0]->decimals;
- agg_result_type(&cached_result_type, args, 2);
+ unsigned_flag= args[0]->unsigned_flag;
+ cached_result_type= args[0]->result_type();
if (cached_result_type == STRING_RESULT &&
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV))
return;
@@ -1616,6 +1633,18 @@ void Item_func_case::fix_length_and_dec()
}
+uint Item_func_case::decimal_precision() const
+{
+ int max_int_part=0;
+ for (uint i=0 ; i < ncases ; i+=2)
+ set_if_bigger(max_int_part, args[i+1]->decimal_int_part());
+
+ if (else_expr_num != -1)
+ set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
+ return min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+}
+
+
/* TODO: Fix this so that it prints the whole CASE expression */
void Item_func_case::print(String *str)
@@ -1708,8 +1737,7 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec()
{
agg_result_type(&cached_result_type, args, arg_count);
- switch (cached_result_type)
- {
+ switch (cached_result_type) {
case STRING_RESULT:
count_only_length();
decimals= NOT_FIXED_DEC;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index e917e13c5aa..a929d509723 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -17,7 +17,7 @@
/* compare and test functions */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -95,6 +95,7 @@ public:
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
bool is_bool_func() { return 1; }
void fix_length_and_dec() { decimals=0; max_length=1; }
+ uint decimal_precision() const { return 1; }
};
class Item_cache;
@@ -208,6 +209,7 @@ public:
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
+ uint decimal_precision() const { return 1; }
friend class Arg_comparator;
};
@@ -410,7 +412,9 @@ public:
const char *func_name() const { return "between"; }
void fix_length_and_dec();
void print(String *str);
+ bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
+ uint decimal_precision() const { return 1; }
};
@@ -445,6 +449,7 @@ public:
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
+ uint decimal_precision() const { return 2; }
};
@@ -485,6 +490,7 @@ public:
void fix_length_and_dec();
const char *func_name() const { return "ifnull"; }
Field *tmp_table_field(TABLE *table);
+ uint decimal_precision() const;
};
@@ -507,6 +513,7 @@ public:
return Item_func::fix_fields(thd, tlist, ref);
}
void fix_length_and_dec();
+ uint decimal_precision() const;
const char *func_name() const { return "if"; }
table_map not_null_tables() const { return 0; }
};
@@ -525,6 +532,7 @@ public:
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return cached_result_type; }
void fix_length_and_dec();
+ uint decimal_precision() const { return args[0]->decimal_precision(); }
const char *func_name() const { return "nullif"; }
void print(String *str) { Item_func::print(str); }
table_map not_null_tables() const { return 0; }
@@ -563,6 +571,7 @@ public:
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec();
+ uint decimal_precision() const;
table_map not_null_tables() const { return 0; }
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
@@ -825,6 +834,7 @@ class Item_func_in :public Item_int_func
}
longlong val_int();
void fix_length_and_dec();
+ uint decimal_precision() const { return 1; }
void cleanup()
{
DBUG_ENTER("Item_func_in::cleanup");
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 24a3f7927ae..db49b7b4ae9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -534,8 +534,10 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
res= make_string_field(t_arg);
break;
case DECIMAL_RESULT:
- res= new Field_new_decimal(max_length + (decimals?1:0), maybe_null,
- name, t_arg, decimals);
+ res= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(),
+ decimals,
+ unsigned_flag),
+ maybe_null, name, t_arg, decimals, unsigned_flag);
break;
case ROW_RESULT:
default:
@@ -590,19 +592,18 @@ void Item_func_numhybrid::fix_num_length_and_dec()
void Item_func::count_decimal_length()
{
- uint32 length= 0;
+ int max_int_part= 0;
decimals= 0;
+ unsigned_flag= 1;
for (uint i=0 ; i < arg_count ; i++)
{
set_if_bigger(decimals, args[i]->decimals);
- set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
+ set_if_bigger(max_int_part, args[i]->decimal_int_part());
+ set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
}
- max_length= length;
- length+= decimals;
- if (length < max_length) // If previous operation gave overflow
- max_length= UINT_MAX32;
- else
- max_length= length;
+ int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
}
@@ -616,8 +617,12 @@ void Item_func::count_decimal_length()
void Item_func::count_only_length()
{
max_length= 0;
+ unsigned_flag= 0;
for (uint i=0 ; i < arg_count ; i++)
+ {
set_if_bigger(max_length, args[i]->max_length);
+ set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
+ }
}
@@ -719,7 +724,6 @@ void Item_num_op::find_num_type(void)
{
decimals= 0;
hybrid_type=INT_RESULT;
- unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
result_precision();
}
DBUG_PRINT("info", ("Type: %s",
@@ -904,6 +908,58 @@ void Item_func_signed::print(String *str)
}
+longlong Item_func_signed::val_int_from_str(int *error)
+{
+ char buff[MAX_FIELD_WIDTH], *end;
+ String tmp(buff,sizeof(buff), &my_charset_bin), *res;
+ longlong value;
+
+ /*
+ For a string result, we must first get the string and then convert it
+ to a longlong
+ */
+
+ if (!(res= args[0]->val_str(&tmp)))
+ {
+ null_value= 1;
+ *error= 0;
+ return 0;
+ }
+ null_value= 0;
+ end= (char*) res->ptr()+ res->length();
+ value= my_strtoll10(res->ptr(), &end, error);
+ if (*error > 0 || end != res->ptr()+ res->length())
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
+ res->c_ptr());
+ return value;
+}
+
+
+longlong Item_func_signed::val_int()
+{
+ longlong value;
+ int error;
+
+ if (args[0]->cast_to_int_type() != STRING_RESULT)
+ {
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ return value;
+ }
+
+ value= val_int_from_str(&error);
+ if (value < 0 && error == 0)
+ {
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Cast to signed converted positive out-of-range integer to "
+ "it's negative complement");
+ }
+ return value;
+}
+
+
void Item_func_unsigned::print(String *str)
{
str->append("cast(", 5);
@@ -913,6 +969,27 @@ void Item_func_unsigned::print(String *str)
}
+longlong Item_func_unsigned::val_int()
+{
+ longlong value;
+ int error;
+
+ if (args[0]->cast_to_int_type() != STRING_RESULT)
+ {
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ return value;
+ }
+
+ value= val_int_from_str(&error);
+ if (error < 0)
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Cast to unsigned converted negative integer to it's "
+ "positive complement");
+ return value;
+}
+
+
String *Item_decimal_typecast::val_str(String *str)
{
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
@@ -1002,9 +1079,17 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
void Item_func_additive_op::result_precision()
{
decimals= max(args[0]->decimals, args[1]->decimals);
- max_length= (max(args[0]->max_length - args[0]->decimals,
- args[1]->max_length - args[1]->decimals) +
- decimals + 1);
+ int max_int_part= max(args[0]->decimal_precision() - args[0]->decimals,
+ args[1]->decimal_precision() - args[1]->decimals);
+ int precision= min(max_int_part + 1 + decimals, DECIMAL_MAX_PRECISION);
+
+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
+ if (result_type() == INT_RESULT)
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ else
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
}
@@ -1099,10 +1184,15 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
void Item_func_mul::result_precision()
{
- decimals= args[0]->decimals + args[1]->decimals;
- max_length= ((args[0]->max_length - args[0]->decimals) +
- (args[1]->max_length - args[1]->decimals) +
- decimals);
+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
+ if (result_type() == INT_RESULT)
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ else
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
+ int precision= min(args[0]->decimal_precision() + args[1]->decimal_precision(),
+ DECIMAL_MAX_PRECISION);
+ max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag);
}
@@ -1134,7 +1224,7 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
if ((null_value= args[1]->null_value))
return 0;
switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
- val1, val2, DECIMAL_DIV_SCALE_INCREASE)) {
+ val1, val2, prec_increment)) {
case E_DEC_TRUNCATED:
case E_DEC_OK:
return decimal_value;
@@ -1149,22 +1239,28 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
void Item_func_div::result_precision()
{
- decimals= (args[0]->decimals + args[0]->decimals +
- DECIMAL_DIV_SCALE_INCREASE);
- max_length= ((args[0]->max_length - args[0]->decimals) +
- (args[1]->max_length - args[1]->decimals) +
- decimals);
+ uint precision=min(args[0]->decimal_precision() + prec_increment,
+ DECIMAL_MAX_PRECISION);
+ /* Integer operations keep unsigned_flag if one of arguments is unsigned */
+ if (result_type() == INT_RESULT)
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ else
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
}
void Item_func_div::fix_length_and_dec()
{
DBUG_ENTER("Item_func_div::fix_length_and_dec");
+ prec_increment= current_thd->variables.div_precincrement;
Item_num_op::fix_length_and_dec();
switch(hybrid_type) {
case REAL_RESULT:
{
- decimals=max(args[0]->decimals,args[1]->decimals)+2;
+ decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
set_if_smaller(decimals, NOT_FIXED_DEC);
max_length=args[0]->max_length - args[0]->decimals + decimals;
uint tmp=float_length(decimals);
@@ -1310,7 +1406,6 @@ void Item_func_neg::fix_num_length_and_dec()
decimals= args[0]->decimals;
/* 1 add because sign can appear */
max_length= args[0]->max_length + 1;
- unsigned_flag= 0;
}
@@ -1322,11 +1417,12 @@ void Item_func_neg::fix_length_and_dec()
/*
If this is in integer context keep the context as integer if possible
(This is how multiplication and other integer functions works)
+ Use val() to get value as arg_type doesn't mean that item is
+ Item_int or Item_real due to existence of Item_param.
*/
if (hybrid_type == INT_RESULT &&
args[0]->type() == INT_ITEM &&
- ((ulonglong) ((Item_uint*) args[0])->value >=
- (ulonglong) LONGLONG_MIN))
+ ((ulonglong) args[0]->val_int() >= (ulonglong) LONGLONG_MIN))
{
/*
Ensure that result is converted to DECIMAL, as longlong can't hold
@@ -1335,6 +1431,7 @@ void Item_func_neg::fix_length_and_dec()
hybrid_type= DECIMAL_RESULT;
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
}
+ unsigned_flag= 0;
DBUG_VOID_RETURN;
}
@@ -1719,17 +1816,65 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
}
-void Item_func_round::fix_num_length_and_dec()
+void Item_func_round::fix_length_and_dec()
{
- max_length= args[0]->max_length;
- decimals= NOT_FIXED_DEC;
- if (args[1]->const_item())
+ unsigned_flag= args[0]->unsigned_flag;
+ if (!args[1]->const_item())
{
- int tmp=(int) args[1]->val_int();
- if (tmp < 0)
- decimals=0;
+ max_length= args[0]->max_length;
+ decimals= args[0]->decimals;
+ hybrid_type= REAL_RESULT;
+ return;
+ }
+
+ int decimals_to_set= max(args[1]->val_int(), 0);
+ if (args[0]->decimals == NOT_FIXED_DEC)
+ {
+ max_length= args[0]->max_length;
+ decimals= min(decimals_to_set, NOT_FIXED_DEC);
+ hybrid_type= REAL_RESULT;
+ return;
+ }
+
+ switch (args[0]->result_type())
+ {
+ case REAL_RESULT:
+ case STRING_RESULT:
+ hybrid_type= REAL_RESULT;
+ decimals= min(decimals_to_set, NOT_FIXED_DEC);
+ max_length= float_length(decimals);
+ break;
+ case INT_RESULT:
+ if (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
+ {
+ /* Here we can keep INT_RESULT */
+ hybrid_type= INT_RESULT;
+ int length_can_increase= !truncate && (args[1]->val_int() < 0);
+ max_length= args[0]->max_length + length_can_increase;
+ decimals= 0;
+ break;
+ }
+ case DECIMAL_RESULT:
+ {
+ hybrid_type= DECIMAL_RESULT;
+ int decimals_delta= args[0]->decimals - decimals_to_set;
+ int precision= args[0]->decimal_precision();
+ if (decimals_delta > 0)
+ {
+ int length_increase= truncate ? 0:1;
+ precision-= decimals_delta - length_increase;
+ decimals= decimals_to_set;
+ }
else
- decimals=min(tmp, NOT_FIXED_DEC);
+ /* Decimals to set is bigger that the original scale */
+ /* we keep original decimals value */
+ decimals= args[0]->decimals;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ break;
+ }
+ default:
+ DBUG_ASSERT(0); /* This result type isn't handled */
}
}
@@ -1807,7 +1952,9 @@ my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
my_decimal val, *value= args[0]->val_decimal(&val);
int dec=(int) args[1]->val_int();
if (dec > 0)
- decimals= dec; // to get correct output
+ {
+ decimals= min(dec, DECIMAL_MAX_SCALE); // to get correct output
+ }
if ((null_value= (args[0]->null_value || args[1]->null_value ||
my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate,
decimal_value) > 1)))
@@ -1899,6 +2046,7 @@ double Item_func_units::val_real()
void Item_func_min_max::fix_length_and_dec()
{
+ int max_int_part=0;
decimals=0;
max_length=0;
maybe_null=1;
@@ -1908,12 +2056,16 @@ void Item_func_min_max::fix_length_and_dec()
{
set_if_bigger(max_length, args[i]->max_length);
set_if_bigger(decimals, args[i]->decimals);
+ set_if_bigger(max_int_part, args[i]->decimal_int_part());
if (!args[i]->maybe_null)
maybe_null=0;
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
}
if (cmp_type == STRING_RESULT)
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
+ else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
+ max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
+ unsigned_flag);
}
@@ -2349,12 +2501,12 @@ longlong Item_func_find_in_set::val_int()
}
str_end= substr_end;
}
- else if (str_end - str_begin == 0 &&
- find_str_len == 0 &&
+ else if (str_end - str_begin == 0 &&
+ find_str_len == 0 &&
wc == (my_wc_t) separator)
return (longlong) ++position;
else
- return (longlong) 0;
+ return LL(0);
}
}
return 0;
@@ -2381,6 +2533,28 @@ longlong Item_func_bit_count::val_int()
#ifdef HAVE_DLOPEN
+void udf_handler::cleanup()
+{
+ if (!not_original)
+ {
+ if (initialized)
+ {
+ if (u_d->func_deinit != NULL)
+ {
+ void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
+ u_d->func_deinit;
+ (*deinit)(&initid);
+ }
+ free_udf(u_d);
+ initialized= FALSE;
+ }
+ if (buffers) // Because of bug in ecc
+ delete [] buffers;
+ buffers= 0;
+ }
+}
+
+
bool
udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
uint arg_count, Item **arguments)
@@ -2653,6 +2827,13 @@ my_decimal *udf_handler::val_decimal(my_bool *null_value, my_decimal *dec_buf)
}
+void Item_udf_func::cleanup()
+{
+ udf.cleanup();
+ Item_func::cleanup();
+}
+
+
double Item_func_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
@@ -2778,21 +2959,8 @@ String *Item_func_udf_str::val_str(String *str)
udf_handler::~udf_handler()
{
- if (!not_original)
- {
- if (initialized)
- {
- if (u_d->func_deinit != NULL)
- {
- void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
- u_d->func_deinit;
- (*deinit)(&initid);
- }
- free_udf(u_d);
- }
- if (buffers) // Because of bug in ecc
- delete [] buffers;
- }
+ /* Everything should be properly cleaned up by this moment. */
+ DBUG_ASSERT(not_original || !(initialized || buffers));
}
#else
@@ -3271,7 +3439,8 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
from the argument if the argument is NULL
and the variable has previously been initialized.
*/
- if (!entry->collation.collation || !args[0]->null_value)
+ null_item= (args[0]->type() == NULL_ITEM);
+ if (!entry->collation.collation || !null_item)
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
cached_result_type= args[0]->result_type();
@@ -3315,8 +3484,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
if (entry->value && entry->value != pos)
my_free(entry->value,MYF(0));
- entry->value=0;
- entry->length=0;
+ entry->value= 0;
+ entry->length= 0;
}
else
{
@@ -3355,9 +3524,9 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
if (type == DECIMAL_RESULT)
((my_decimal*)entry->value)->fix_buffer_pointer();
entry->length= length;
- entry->type=type;
entry->collation.set(cs, dv);
}
+ entry->type=type;
return 0;
}
@@ -3366,6 +3535,12 @@ bool
Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
CHARSET_INFO *cs, Derivation dv)
{
+ /*
+ If we set a variable explicitely to NULL then keep the old
+ result type of the variable
+ */
+ if ((null_value= args[0]->null_value) && null_item)
+ type= entry->type; // Don't change type of item
if (::update_hash(entry, (null_value= args[0]->null_value),
ptr, length, type, cs, dv))
{
@@ -3833,15 +4008,17 @@ void Item_func_get_user_var::fix_length_and_dec()
switch (var_entry->type) {
case REAL_RESULT:
max_length= DBL_DIG + 8;
+ break;
case INT_RESULT:
max_length= MAX_BIGINT_WIDTH;
+ decimals=0;
break;
case STRING_RESULT:
max_length= MAX_BLOB_WIDTH;
break;
case DECIMAL_RESULT:
- max_length= DECIMAL_MAX_LENGTH;
- decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1);
+ max_length= DECIMAL_MAX_STR_LENGTH;
+ decimals= DECIMAL_MAX_SCALE;
break;
case ROW_RESULT: // Keep compiler happy
default:
@@ -4503,29 +4680,40 @@ Item_func_sp::func_name() const
Field *
Item_func_sp::sp_result_field(void) const
{
- Field *field= 0;
- THD *thd= current_thd;
+ Field *field;
DBUG_ENTER("Item_func_sp::sp_result_field");
- if (m_sp)
+
+ if (!m_sp)
{
- if (dummy_table->s == NULL)
+ if (!(m_sp= sp_find_function(current_thd, m_name, TRUE)))
{
- char *empty_name= (char *) "";
- TABLE_SHARE *share;
- dummy_table->s= share= &dummy_table->share_not_to_be_used;
- dummy_table->alias = empty_name;
- dummy_table->maybe_null = maybe_null;
- dummy_table->in_use= current_thd;
- share->table_cache_key = empty_name;
- share->table_name = empty_name;
- share->table_name = empty_name;
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ DBUG_RETURN(0);
}
- field= m_sp->make_field(max_length, name, dummy_table);
}
- DBUG_RETURN(field);
+ if (!dummy_table->s)
+ {
+ char *empty_name= (char *) "";
+ TABLE_SHARE *share;
+ dummy_table->s= share= &dummy_table->share_not_to_be_used;
+ dummy_table->alias = empty_name;
+ dummy_table->maybe_null = maybe_null;
+ dummy_table->in_use= current_thd;
+ share->table_cache_key = empty_name;
+ share->table_name = empty_name;
+ }
+ DBUG_RETURN(m_sp->make_field(max_length, name, dummy_table));
}
+/*
+ Execute function & store value in field
+
+ RETURN
+ 0 value <> NULL
+ 1 value = NULL or error
+*/
+
int
Item_func_sp::execute(Field **flp)
{
@@ -4545,7 +4733,7 @@ Item_func_sp::execute(Field **flp)
f->null_bit= 1;
}
it->save_in_field(f, 1);
- return f->is_null();
+ return null_value= f->is_null();
}
@@ -4561,11 +4749,12 @@ Item_func_sp::execute(Item **itp)
#endif
if (! m_sp)
- m_sp= sp_find_function(thd, m_name, TRUE); // cache only
- if (! m_sp)
{
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
- DBUG_RETURN(-1);
+ if (!(m_sp= sp_find_function(thd, m_name, TRUE)))
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ DBUG_RETURN(-1);
+ }
}
old_client_capabilites= thd->client_capabilities;
@@ -4590,9 +4779,24 @@ Item_func_sp::execute(Item **itp)
DBUG_RETURN(-1);
}
#endif
+ /*
+ Like for SPs, we don't binlog the substatements. If the statement which
+ called this function is an update statement, it will be binlogged; but if
+ it's not (e.g. SELECT myfunc()) it won't be binlogged (documented known
+ problem).
+ */
+ tmp_disable_binlog(thd); /* don't binlog the substatements */
res= m_sp->execute_function(thd, args, arg_count, itp);
+ reenable_binlog(thd);
+ if (res && mysql_bin_log.is_open() &&
+ (m_sp->m_chistics->daccess == SP_CONTAINS_SQL ||
+ m_sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_FAILED_ROUTINE_BREAK_BINLOG,
+ ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_restore_security_context(thd, m_sp, &save_ctx);
#endif
@@ -4612,15 +4816,12 @@ Item_func_sp::make_field(Send_field *tmp_field)
{
Field *field;
DBUG_ENTER("Item_func_sp::make_field");
- if (! m_sp)
- m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field()))
{
field->make_field(tmp_field);
delete field;
DBUG_VOID_RETURN;
}
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
DBUG_VOID_RETURN;
}
@@ -4629,20 +4830,17 @@ Item_func_sp::make_field(Send_field *tmp_field)
enum enum_field_types
Item_func_sp::field_type() const
{
- Field *field= 0;
+ Field *field;
DBUG_ENTER("Item_func_sp::field_type");
if (result_field)
DBUG_RETURN(result_field->type());
- if (! m_sp)
- m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field()))
{
enum_field_types result= field->type();
delete field;
DBUG_RETURN(result);
}
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(MYSQL_TYPE_VARCHAR);
}
@@ -4650,68 +4848,40 @@ Item_func_sp::field_type() const
Item_result
Item_func_sp::result_type() const
{
- Field *field= 0;
+ Field *field;
DBUG_ENTER("Item_func_sp::result_type");
DBUG_PRINT("info", ("m_sp = %p", m_sp));
if (result_field)
DBUG_RETURN(result_field->result_type());
- if (! m_sp)
- m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
if ((field= sp_result_field()))
{
Item_result result= field->result_type();
delete field;
DBUG_RETURN(result);
}
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(STRING_RESULT);
}
void
Item_func_sp::fix_length_and_dec()
{
- Field *field= result_field;
+ Field *field;
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
if (result_field)
{
decimals= result_field->decimals();
- max_length= result_field->representation_length();
+ max_length= result_field->field_length;
DBUG_VOID_RETURN;
}
- if (! m_sp)
- m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
- if (! m_sp)
- {
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
- }
- else
- {
- if (!field)
- field= sp_result_field();
-
- decimals= field->decimals();
- max_length= field->representation_length();
-
- switch (field->result_type()) {
- case STRING_RESULT:
- maybe_null= 1;
- case REAL_RESULT:
- case INT_RESULT:
- case DECIMAL_RESULT:
- break;
- case ROW_RESULT:
- default:
- // This case should never be chosen
- DBUG_ASSERT(0);
- break;
- }
-
- if (field != result_field)
- delete field;
- }
+ if (!(field= sp_result_field()))
+ DBUG_VOID_RETURN;
+ decimals= field->decimals();
+ max_length= field->field_length;
+ maybe_null= 1;
+ delete field;
DBUG_VOID_RETURN;
}
@@ -4719,11 +4889,10 @@ Item_func_sp::fix_length_and_dec()
longlong Item_func_found_rows::val_int()
{
DBUG_ASSERT(fixed == 1);
- THD *thd= current_thd;
-
- return thd->found_rows();
+ return current_thd->found_rows();
}
+
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index cb0b7dc02a4..b53f2a0b9c6 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -17,7 +17,7 @@
/* Function items used by mysql */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -262,15 +262,13 @@ public:
null_value= args[0]->null_value;
return tmp;
}
- longlong val_int()
- {
- longlong tmp= args[0]->val_int();
- null_value= args[0]->null_value;
- return tmp;
- }
+ longlong val_int();
+ longlong val_int_from_str(int *error);
void fix_length_and_dec()
{ max_length=args[0]->max_length; unsigned_flag=0; }
void print(String *str);
+ uint decimal_precision() const { return args[0]->decimal_precision(); }
+
};
@@ -281,6 +279,7 @@ public:
const char *func_name() const { return "cast_as_unsigned"; }
void fix_length_and_dec()
{ max_length=args[0]->max_length; unsigned_flag=1; }
+ longlong val_int();
void print(String *str);
};
@@ -299,7 +298,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal*);
enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
+ enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
void fix_length_and_dec() {};
};
@@ -349,6 +348,7 @@ public:
class Item_func_div :public Item_num_op
{
public:
+ uint prec_increment;
Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {}
longlong int_op() { DBUG_ASSERT(0); return 0; }
double real_op();
@@ -393,6 +393,7 @@ public:
const char *func_name() const { return "-"; }
void fix_length_and_dec();
void fix_num_length_and_dec();
+ uint decimal_precision() const { return args[0]->decimal_precision(); }
};
@@ -596,7 +597,7 @@ public:
double real_op();
longlong int_op();
my_decimal *decimal_op(my_decimal *);
- void fix_num_length_and_dec();
+ void fix_length_and_dec();
};
@@ -878,6 +879,7 @@ public:
fixed= 1;
return res;
}
+ void cleanup();
Item_result result_type () const { return udf.result_type(); }
table_map not_null_tables() const { return 0; }
};
@@ -1071,6 +1073,7 @@ class Item_func_set_user_var :public Item_func
char buffer[MAX_FIELD_WIDTH];
String value;
my_decimal decimal_buff;
+ bool null_item;
union
{
longlong vint;
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 1a8cb50081b..b9f2ec8a6ca 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -55,8 +55,11 @@ String *Item_func_geometry_from_text::val_str(String *str)
return 0;
str->length(0);
str->q_append(srid);
- if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
- return 0;
+ if (!Geometry::create_from_wkt(&buffer, &trs, str, 0))
+ /* We shouldn't return NULL here as NULL is a legal spatial object */
+ /* Geometry::bad_spatial_data will produce error message beeing stored*/
+ /* in GEOMETRY field */
+ return &Geometry::bad_geometry_data;
return str;
}
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index e19036cc982..c45fb88a48a 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -19,7 +19,7 @@
#ifdef HAVE_SPATIAL
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 3fe1b819f36..fb7827ef932 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1013,7 +1013,7 @@ String *Item_func_substr::val_str(String *str)
if ((null_value=(args[0]->null_value || args[1]->null_value ||
(arg_count == 3 && args[2]->null_value))))
return 0; /* purecov: inspected */
- start= (int32)((start < 0) ? res->length() + start : start -1);
+ start= (int32)((start < 0) ? res->numchars() + start : start -1);
start=res->charpos(start);
length=res->charpos(length,start);
if (start < 0 || (uint) start+1 > res->length() || length <= 0)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index eec81f953fb..4c44db49489 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -17,7 +17,7 @@
/* This file defines all string functions */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 1a407c695b2..84935429353 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -16,7 +16,7 @@
/* subselect Item */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -122,6 +122,9 @@ public:
friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
friend bool Item_param::fix_fields(THD *, TABLE_LIST *, Item **);
+ friend void mark_select_range_as_dependent(THD*,
+ st_select_lex*, st_select_lex*,
+ Field*, Item*, Item_ident*);
};
/* single value subselect */
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 3dd4b6618a2..a5694189976 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -156,8 +156,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
collation.collation);
return make_string_field(table);
case DECIMAL_RESULT:
- return new Field_new_decimal(max_length - (decimals?1:0),
- maybe_null, name, table, decimals);
+ return new Field_new_decimal(max_length, maybe_null, name, table,
+ decimals, unsigned_flag);
case ROW_RESULT:
default:
// This case should never be choosen
@@ -240,6 +240,8 @@ Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
case REAL_RESULT:
sum= item->sum;
break;
+ case STRING_RESULT: // This can happen with ROLLUP. Note that the value is already
+ break; // copied at function call.
case ROW_RESULT:
default:
DBUG_ASSERT(0);
@@ -372,13 +374,16 @@ void Item_sum_sum::fix_length_and_dec()
break;
case INT_RESULT:
case DECIMAL_RESULT:
+ {
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
- max_length= min(args[0]->max_length + DECIMAL_LONGLONG_DIGITS,
- DECIMAL_MAX_LENGTH);
+ int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
curr_dec_buff= 0;
hybrid_type= DECIMAL_RESULT;
my_decimal_set_zero(dec_buffs);
break;
+ }
case ROW_RESULT:
default:
DBUG_ASSERT(0);
@@ -582,7 +587,10 @@ bool Item_sum_distinct::setup(THD *thd)
DBUG_ENTER("Item_sum_distinct::setup");
- DBUG_ASSERT(tree == 0); /* setup can not be called twice */
+ /*
+ Setup can be called twice for ROLLUP items. This is a bug.
+ Please add DBUG_ASSERT(tree == 0) here when it's fixed.
+ */
/*
Virtual table and the tree are created anew on each re-execution of
@@ -725,11 +733,12 @@ void
Item_sum_avg_distinct::fix_length_and_dec()
{
Item_sum_distinct::fix_length_and_dec();
+ prec_increment= current_thd->variables.div_precincrement;
/*
AVG() will divide val by count. We need to reserve digits
after decimal point as the result can be fractional.
*/
- decimals= min(decimals + 4, NOT_FIXED_DEC);
+ decimals= min(decimals + prec_increment, NOT_FIXED_DEC);
}
@@ -790,14 +799,19 @@ void Item_sum_avg::fix_length_and_dec()
{
Item_sum_sum::fix_length_and_dec();
maybe_null=null_value=1;
- decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
+ prec_increment= current_thd->variables.div_precincrement;
if (hybrid_type == DECIMAL_RESULT)
{
- f_scale= args[0]->decimals;
- max_length= DECIMAL_MAX_LENGTH + (f_scale ? 1 : 0);
- f_precision= DECIMAL_MAX_LENGTH;
+ int precision= args[0]->decimal_precision() + prec_increment;
+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
+ f_precision= min(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
+ f_scale= args[0]->decimals;
dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
}
+ else
+ decimals= min(args[0]->decimals + prec_increment, NOT_FIXED_DEC);
}
@@ -822,8 +836,8 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table,
0, name, table, &my_charset_bin);
}
if (hybrid_type == DECIMAL_RESULT)
- return new Field_new_decimal(f_precision,
- maybe_null, name, table, f_scale);
+ return new Field_new_decimal(max_length, maybe_null, name, table,
+ decimals, unsigned_flag);
return new Field_double(max_length, maybe_null, name, table, decimals);
}
@@ -868,7 +882,7 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
}
sum_dec= Item_sum_sum::val_decimal(&sum);
int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &cnt);
- my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, 4);
+ my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, prec_increment);
return val;
}
@@ -905,7 +919,8 @@ Item *Item_sum_std::copy_or_same(THD* thd)
Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
- cur_dec(item->cur_dec), count(item->count), sample(item->sample)
+ cur_dec(item->cur_dec), count(item->count), sample(item->sample),
+ prec_increment(item->prec_increment)
{
if (hybrid_type == DECIMAL_RESULT)
{
@@ -929,20 +944,21 @@ void Item_sum_variance::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
maybe_null= null_value= 1;
- decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
+ prec_increment= current_thd->variables.div_precincrement;
switch (args[0]->result_type()) {
case REAL_RESULT:
case STRING_RESULT:
+ decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
hybrid_type= REAL_RESULT;
sum= 0.0;
break;
case INT_RESULT:
case DECIMAL_RESULT:
- /*
- SUM result can't be longer than length(arg)*2 +
- digits_after_the_point_to_add
- */
- max_length= args[0]->max_length*2 + 4;
+ {
+ int precision= args[0]->decimal_precision()*2 + prec_increment;
+ decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length(precision, decimals,
+ unsigned_flag);
cur_dec= 0;
hybrid_type= DECIMAL_RESULT;
my_decimal_set_zero(dec_sum);
@@ -954,12 +970,15 @@ void Item_sum_variance::fix_length_and_dec()
column_value * column_value
*/
f_scale0= args[0]->decimals;
- f_precision0= DECIMAL_MAX_LENGTH / 2;
- f_scale1= min(f_scale0 * 2, NOT_FIXED_DEC - 1);
- f_precision1= DECIMAL_MAX_LENGTH;
+ f_precision0= min(args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS,
+ DECIMAL_MAX_PRECISION);
+ f_scale1= min(args[0]->decimals * 2, DECIMAL_MAX_SCALE);
+ f_precision1= min(args[0]->decimal_precision()*2 + DECIMAL_LONGLONG_DIGITS,
+ DECIMAL_MAX_PRECISION);
dec_bin_size0= my_decimal_get_binary_size(f_precision0, f_scale0);
dec_bin_size1= my_decimal_get_binary_size(f_precision1, f_scale1);
break;
+ }
case ROW_RESULT:
default:
DBUG_ASSERT(0);
@@ -997,8 +1016,8 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table,
0, name, table, &my_charset_bin);
}
if (hybrid_type == DECIMAL_RESULT)
- return new Field_new_decimal(DECIMAL_MAX_LENGTH,
- maybe_null, name, table, f_scale1 + 4);
+ return new Field_new_decimal(max_length, maybe_null, name, table,
+ decimals, unsigned_flag);
return new Field_double(max_length, maybe_null,name,table,decimals);
}
@@ -1083,9 +1102,11 @@ my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf)
int2my_decimal(E_DEC_FATAL_ERROR, count-sample, 0, &count1_buf);
my_decimal_mul(E_DEC_FATAL_ERROR, &sum_sqr_buf,
dec_sum+cur_dec, dec_sum+cur_dec);
- my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &sum_sqr_buf, &count_buf, 2);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &sum_sqr_buf, &count_buf, prec_increment);
my_decimal_sub(E_DEC_FATAL_ERROR, &sum_sqr_buf, dec_sqr+cur_dec, dec_buf);
- my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &sum_sqr_buf, &count1_buf, 2);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &sum_sqr_buf, &count1_buf, prec_increment);
return dec_buf;
}
@@ -1929,10 +1950,12 @@ Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
{
name=item->name;
decimals=item->decimals;
- max_length=item->max_length;
+ max_length= item->max_length;
+ unsigned_flag= item->unsigned_flag;
field=item->result_field;
maybe_null=1;
hybrid_type= res_type;
+ prec_increment= item->prec_increment;
if (hybrid_type == DECIMAL_RESULT)
{
f_scale= item->f_scale;
@@ -1941,7 +1964,6 @@ Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
}
}
-
double Item_avg_field::val_real()
{
// fix_fields() never calls for this Item
@@ -1982,7 +2004,8 @@ my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf)
binary2my_decimal(E_DEC_FATAL_ERROR,
field->ptr, &dec_field, f_precision, f_scale);
int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count);
- my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_field, &dec_count, 4);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &dec_field, &dec_count, prec_increment);
return dec_buf;
}
@@ -2054,9 +2077,11 @@ Item_variance_field::Item_variance_field(Item_sum_variance *item)
name=item->name;
decimals=item->decimals;
max_length=item->max_length;
+ unsigned_flag= item->unsigned_flag;
field=item->result_field;
maybe_null=1;
sample= item->sample;
+ prec_increment= item->prec_increment;
if ((hybrid_type= item->hybrid_type) == DECIMAL_RESULT)
{
f_scale0= item->f_scale0;
@@ -2116,9 +2141,10 @@ my_decimal *Item_variance_field::val_decimal(my_decimal *dec_buf)
binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr+dec_bin_size0,
&dec_sqr, f_precision1, f_scale1);
my_decimal_mul(E_DEC_FATAL_ERROR, &tmp, &dec_sum, &dec_sum);
- my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &tmp, &dec_count, 2);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &tmp, &dec_count, prec_increment);
my_decimal_sub(E_DEC_FATAL_ERROR, &dec_sum, &dec_sqr, dec_buf);
- my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_sum, &dec1_count, 2);
+ my_decimal_div(E_DEC_FATAL_ERROR, dec_buf,
+ &dec_sum, &dec1_count, prec_increment);
return dec_buf;
}
@@ -2430,6 +2456,17 @@ bool Item_udf_sum::add()
DBUG_RETURN(0);
}
+void Item_udf_sum::cleanup()
+{
+ /*
+ udf_handler::cleanup() nicely handles case when we have not
+ original item but one created by copy_or_same() method.
+ */
+ udf.cleanup();
+ Item_sum::cleanup();
+}
+
+
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_sum_udf_float(thd, this);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 8c8360b0726..bb5d31b4b4f 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -17,7 +17,7 @@
/* classes for sum functions */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -237,6 +237,7 @@ private:
Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original)
:Item_sum_distinct(thd, original) {}
public:
+ uint prec_increment;
Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {}
void fix_length_and_dec();
@@ -343,8 +344,8 @@ class Item_avg_field :public Item_result_field
public:
Field *field;
Item_result hybrid_type;
- uint f_precision, f_scale;
- uint dec_bin_size;
+ uint f_precision, f_scale, dec_bin_size;
+ uint prec_increment;
Item_avg_field(Item_result res_type, Item_sum_avg *item);
enum Type type() const { return FIELD_AVG_ITEM; }
double val_real();
@@ -366,12 +367,14 @@ class Item_sum_avg :public Item_sum_sum
{
public:
ulonglong count;
- uint f_precision, f_scale;
- uint dec_bin_size;
+ uint prec_increment;
+ uint f_precision, f_scale, dec_bin_size;
Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {}
Item_sum_avg(THD *thd, Item_sum_avg *item)
- :Item_sum_sum(thd, item), count(item->count) {}
+ :Item_sum_sum(thd, item), count(item->count),
+ prec_increment(item->prec_increment) {}
+
void fix_length_and_dec();
enum Sumfunctype sum_func () const {return AVG_FUNC;}
void clear();
@@ -402,6 +405,7 @@ public:
uint f_precision1, f_scale1;
uint dec_bin_size0, dec_bin_size1;
uint sample;
+ uint prec_increment;
Item_variance_field(Item_sum_variance *item);
enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val_real();
@@ -446,6 +450,7 @@ public:
uint f_precision1, f_scale1;
uint dec_bin_size0, dec_bin_size1;
uint sample;
+ uint prec_increment;
Item_sum_variance(Item *item_par, uint sample_arg) :Item_sum_num(item_par),
hybrid_type(REAL_RESULT), cur_dec(0), count(0), sample(sample_arg)
@@ -662,6 +667,7 @@ public:
bool add();
void reset_field() {};
void update_field() {};
+ void cleanup();
};
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index ab511ae2883..c8fb2b39836 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -17,7 +17,7 @@
/* Function items used by mysql */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/key.cc b/sql/key.cc
index 3299c3db8f8..4bd71d2fa47 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -197,12 +197,6 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
(key_part->null_bit == 128),
field->bit_ofs, field->bit_len);
}
- else
- {
- clr_rec_bits(to_record + key_part->null_offset +
- (key_part->null_bit == 128),
- field->bit_ofs, field->bit_len);
- }
}
if (key_part->key_part_flag & HA_BLOB_PART)
{
diff --git a/sql/log.cc b/sql/log.cc
index fc74223d7b6..91428cf41be 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -956,9 +956,9 @@ bool MYSQL_LOG::reset_logs(THD* thd)
my_delete(index_file_name, MYF(MY_WME)); // Reset (open will update)
if (!thd->slave_thread)
need_start_event=1;
- open_index_file(index_file_name, 0);
- open(save_name, save_log_type, 0,
- io_cache_type, no_auto_events, max_size, 0);
+ if (!open_index_file(index_file_name, 0))
+ open(save_name, save_log_type, 0,
+ io_cache_type, no_auto_events, max_size, 0);
my_free((gptr) save_name, MYF(0));
err:
@@ -1589,7 +1589,7 @@ bool MYSQL_LOG::write(Log_event *event_info)
present event could be about a non-transactional table, but still we need
to write to the binlog cache in that case to handle updates to mixed
trans/non-trans table types the best possible in binlogging)
- - or if the event asks for it (cache_stmt == true).
+ - or if the event asks for it (cache_stmt == TRUE).
*/
if (opt_using_transactions && thd)
{
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 86d31a9c2e8..42134d2b990 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -955,6 +955,18 @@ void Query_log_event::pack_info(Protocol *protocol)
#ifndef MYSQL_CLIENT
+/* Utility function for the next method */
+static void write_str_with_code_and_len(char **dst, const char *src,
+ int len, uint code)
+{
+ DBUG_ASSERT(src);
+ *((*dst)++)= code;
+ *((*dst)++)= (uchar) len;
+ bmove(*dst, src, len);
+ (*dst)+= len;
+}
+
+
/*
Query_log_event::write()
@@ -1039,12 +1051,10 @@ bool Query_log_event::write(IO_CACHE* file)
int8store(start, (ulonglong)sql_mode);
start+= 8;
}
- if (catalog_len) // i.e. "catalog inited" (false for 4.0 events)
+ if (catalog_len) // i.e. this var is inited (false for 4.0 events)
{
- *start++= Q_CATALOG_NZ_CODE;
- *start++= (uchar) catalog_len;
- bmove(start, catalog, catalog_len);
- start+= catalog_len;
+ write_str_with_code_and_len((char **)(&start),
+ catalog, catalog_len, Q_CATALOG_NZ_CODE);
/*
In 5.0.x where x<4 masters we used to store the end zero here. This was
a waste of one byte so we don't do it in x>=4 masters. We change code to
@@ -1176,6 +1186,25 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
#endif /* MYSQL_CLIENT */
+/* 2 utility functions for the next method */
+
+static void get_str_len_and_pointer(const char **dst, const char **src, uint *len)
+{
+ if ((*len= **src))
+ *dst= *src + 1; // Will be copied later
+ (*src)+= *len+1;
+}
+
+
+static void copy_str_and_move(char **dst, const char **src, uint len)
+{
+ memcpy(*dst, *src, len);
+ *src= *dst;
+ (*dst)+= len;
+ *(*dst)++= 0;
+}
+
+
/*
Query_log_event::Query_log_event()
This is used by the SQL slave thread to prepare the event before execution.
@@ -1264,9 +1293,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
break;
}
case Q_CATALOG_NZ_CODE:
- if ((catalog_len= *pos))
- catalog= (char*) pos+1; // Will be copied later
- pos+= catalog_len+1;
+ get_str_len_and_pointer(&catalog, (const char **)(&pos), &catalog_len);
break;
case Q_AUTO_INCREMENT:
auto_increment_increment= uint2korr(pos);
@@ -1282,9 +1309,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
}
case Q_TIME_ZONE_CODE:
{
- if ((time_zone_len= *pos))
- time_zone_str= (char *)(pos+1);
- pos+= time_zone_len+1;
+ get_str_len_and_pointer(&time_zone_str, (const char **)(&pos), &time_zone_len);
break;
}
case Q_CATALOG_CODE: /* for 5.0.x where 0<=x<=3 masters */
@@ -1308,12 +1333,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
if (catalog_len) // If catalog is given
{
if (likely(catalog_nz)) // true except if event comes from 5.0.0|1|2|3.
- {
- memcpy(start, catalog, catalog_len);
- catalog= start;
- start+= catalog_len;
- *start++= 0;
- }
+ copy_str_and_move(&start, &catalog, catalog_len);
else
{
memcpy(start, catalog, catalog_len+1); // copy end 0
@@ -1322,12 +1342,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
}
}
if (time_zone_len)
- {
- memcpy(start, time_zone_str, time_zone_len);
- time_zone_str= start;
- start+= time_zone_len;
- *start++= 0;
- }
+ copy_str_and_move(&start, &time_zone_str, time_zone_len);
+
/* A 2nd variable part; this is common to all versions */
memcpy((char*) start, end, data_len); // Copy db and query
start[data_len]= '\0'; // End query with \0 (For safetly)
diff --git a/sql/log_event.h b/sql/log_event.h
index 2985fcabb50..f8989c4994a 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -234,13 +234,12 @@ struct sql_ex_info
/* these are codes, not offsets; not more than 256 values (1 byte). */
#define Q_FLAGS2_CODE 0
#define Q_SQL_MODE_CODE 1
-#ifndef TO_BE_DELETED
/*
Q_CATALOG_CODE is catalog with end zero stored; it is used only by MySQL
- 5.0.x where 0<=x<=3.
+ 5.0.x where 0<=x<=3. We have to keep it to be able to replicate these
+ old masters.
*/
#define Q_CATALOG_CODE 2
-#endif
#define Q_AUTO_INCREMENT 3
#define Q_CHARSET_CODE 4
#define Q_TIME_ZONE_CODE 5
diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc
index b4bbef4a637..f188d27ff78 100644
--- a/sql/my_decimal.cc
+++ b/sql/my_decimal.cc
@@ -43,9 +43,9 @@ int decimal_operation_results(int result)
break;
case E_DEC_OVERFLOW:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_WARN_DATA_OUT_OF_RANGE,
- ER(ER_WARN_DATA_OUT_OF_RANGE),
- "", (long)-1);
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE),
+ "DECIMAL", "");
break;
case E_DEC_DIV_ZERO:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
@@ -81,7 +81,7 @@ int decimal_operation_results(int result)
*/
int my_decimal2string(uint mask, const my_decimal *d,
- int fixed_prec, int fixed_dec,
+ uint fixed_prec, uint fixed_dec,
char filler, String *str)
{
int length= (fixed_prec ? (fixed_prec + 1) : my_decimal_string_length(d));
@@ -89,7 +89,7 @@ int my_decimal2string(uint mask, const my_decimal *d,
if (str->alloc(length))
return check_result(mask, E_DEC_OOM);
result= decimal2string((decimal_t*) d, (char*) str->ptr(),
- &length, fixed_prec, fixed_dec,
+ &length, (int)fixed_prec, fixed_dec,
filler);
str->length(length);
return check_result(mask, result);
@@ -123,7 +123,7 @@ int my_decimal2binary(uint mask, const my_decimal *d, char *bin, int prec,
int err1= E_DEC_OK, err2;
my_decimal rounded;
my_decimal2decimal(d, &rounded);
- decimal_optimize_fraction(&rounded);
+ rounded.frac= decimal_actual_fraction(&rounded);
if (scale < rounded.frac)
{
err1= E_DEC_TRUNCATED;
@@ -220,18 +220,16 @@ print_decimal_buff(const my_decimal *dec, const byte* ptr, int length)
}
-void dbug_print_decimal(const char *tag, const char *format, my_decimal *val)
+const char *dbug_decimal_as_string(char *buff, const my_decimal *val)
{
- char buff[DECIMAL_MAX_STR_LENGTH];
- String str(buff, sizeof(buff), &my_charset_bin);
+ int length= DECIMAL_MAX_STR_LENGTH;
if (!val)
- str.set("NULL", 4, &my_charset_bin);
- else
- my_decimal2string(0, val, 0, 0, 0, &str);
- DBUG_PRINT(tag, (format, (char*) str.ptr()));
+ return "NULL";
+ (void)decimal2string((decimal_t*) val, buff, &length, 0,0,0);
+ return buff;
}
-#endif
+#endif /*DBUG_OFF*/
#endif /*MYSQL_CLIENT*/
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index 03801390d82..27fd33cffbe 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -35,27 +35,27 @@ C_MODE_END
#define DECIMAL_LONG_DIGITS 10
#define DECIMAL_LONG3_DIGITS 8
-/* number of digits on which we increase scale of devision result */
-#define DECIMAL_DIV_SCALE_INCREASE 5
-
/* maximum length of buffer in our big digits (uint32) */
-#define DECIMAL_BUFF_LENGTH 8
+#define DECIMAL_BUFF_LENGTH 9
/*
- maximum guaranteed length of number in decimal digits (number of our
+ maximum guaranteed precision of number in decimal digits (number of our
digits * number of decimal digits in one our big digit - number of decimal
digits in one our big digit decreased on 1 (because we always put decimal
point on the border of our big digits))
*/
-#define DECIMAL_MAX_LENGTH ((8 * 9) - 8)
+#define DECIMAL_MAX_PRECISION ((DECIMAL_BUFF_LENGTH * 9) - 8*2)
+#define DECIMAL_MAX_SCALE 30
+#define DECIMAL_NOT_SPECIFIED 31
+
/*
maximum length of string representation (number of maximum decimal
digits + 1 position for sign + 1 position for decimal point)
*/
-#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_LENGTH + 2)
+#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_PRECISION + 2)
/*
maximum size of packet length
*/
-#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_LENGTH
+#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
inline uint my_decimal_size(uint precision, uint scale)
@@ -68,6 +68,12 @@ inline uint my_decimal_size(uint precision, uint scale)
}
+inline int my_decimal_int_part(uint precision, uint decimals)
+{
+ return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
+}
+
+
/*
my_decimal class limits 'decimal_t' type to what we need in MySQL
It contains internally all necessary space needed by the instance so
@@ -99,15 +105,16 @@ public:
bool sign() const { return decimal_t::sign; }
void sign(bool s) { decimal_t::sign= s; }
+ uint precision() const { return intg + frac; }
};
#ifndef DBUG_OFF
void print_decimal(const my_decimal *dec);
void print_decimal_buff(const my_decimal *dec, const byte* ptr, int length);
-void dbug_print_decimal(const char *tag, const char *format, my_decimal *val);
+const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
#else
-#define dbug_print_decimal(A,B,C)
+#define dbug_decimal_as_string(A) NULL
#endif
#ifndef MYSQL_CLIENT
@@ -126,6 +133,18 @@ inline int check_result(uint mask, int result)
return result;
}
+inline uint my_decimal_length_to_precision(uint length, uint scale,
+ bool unsigned_flag)
+{
+ return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1));
+}
+
+inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
+ bool unsigned_flag)
+{
+ set_if_smaller(precision, DECIMAL_MAX_PRECISION);
+ return (uint32)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1));
+}
inline
int my_decimal_string_length(const my_decimal *d)
@@ -209,8 +228,8 @@ int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
#ifndef MYSQL_CLIENT
-int my_decimal2string(uint mask, const my_decimal *d, int fixed_prec,
- int fixed_dec, char filler, String *str);
+int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
+ uint fixed_dec, char filler, String *str);
#endif
inline
@@ -326,7 +345,8 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
inline
void max_my_decimal(my_decimal *to, int precision, int frac)
{
- DBUG_ASSERT(precision <= DECIMAL_MAX_LENGTH);
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
+ (frac <= DECIMAL_MAX_SCALE));
max_decimal(precision, frac, (decimal_t*) to);
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 06c946114eb..25490b04ab3 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -183,6 +183,11 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#else
#define IF_INNOBASE_DB(A, B) (B)
#endif
+#ifdef __NETWARE__
+#define IF_NETWARE(A,B) (A)
+#else
+#define IF_NETWARE(A,B) (B)
+#endif
#if defined(__WIN__) || defined(OS2)
#define IF_WIN(A,B) (A)
@@ -263,6 +268,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define OPTION_SCHEMA_TABLE (1L << 29)
/* Flag set if setup_tables already done */
#define OPTION_SETUP_TABLES_DONE (1L << 30)
+/* Thr following is used to detect a conflict with DISTINCT
+ in the user query has requested */
+#define SELECT_ALL (ULL(1) << 32)
/*
Maximum length of time zone name that we support
@@ -1088,7 +1096,7 @@ extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern my_bool sp_automatic_privileges;
-extern my_bool opt_old_style_user_limits;
+extern my_bool opt_old_style_user_limits, trust_routine_creators;
extern uint opt_crash_binlog_innodb;
extern char *shared_memory_base_name, *mysqld_unix_port;
extern bool opt_enable_shared_memory;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 169c9e057b5..90d4f9b9a99 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -303,7 +303,7 @@ my_bool opt_log_queries_not_using_indexes= 0;
my_bool lower_case_file_system= 0;
my_bool opt_large_pages= 0;
uint opt_large_page_size= 0;
-my_bool opt_old_style_user_limits= 0;
+my_bool opt_old_style_user_limits= 0, trust_routine_creators= 0;
/*
True if there is at least one per-hour limit for some user, so we should
check them before each query (and possibly reset counters when hour is
@@ -2670,8 +2670,8 @@ static int init_server_components()
Update log is removed since 5.0. But we still accept the option.
The idea is if the user already uses the binlog and the update log,
we completely ignore any option/variable related to the update log, like
- if the update log did not exist. But if the user uses only the update log,
- then we translate everything into binlog for him (with warnings).
+ if the update log did not exist. But if the user uses only the update
+ log, then we translate everything into binlog for him (with warnings).
Implementation of the above :
- If mysqld is started with --log-update and --log-bin,
ignore --log-update (print a warning), push a warning when SQL_LOG_UPDATE
@@ -2685,11 +2685,11 @@ static int init_server_components()
Note that we tell the user that --sql-bin-update-same is deprecated and
does nothing, and we don't take into account if he used this option or
- not; but internally we give this variable a value to have the behaviour we
- want (i.e. have SQL_LOG_UPDATE influence SQL_LOG_BIN or not).
+ not; but internally we give this variable a value to have the behaviour
+ we want (i.e. have SQL_LOG_UPDATE influence SQL_LOG_BIN or not).
As sql-bin-update-same, log-update and log-bin cannot be changed by the
- user after starting the server (they are not variables), the user will not
- later interfere with the settings we do here.
+ user after starting the server (they are not variables), the user will
+ not later interfere with the settings we do here.
*/
if (opt_bin_log)
{
@@ -2703,7 +2703,7 @@ version 5.0 and above. It is replaced by the binary log.");
opt_bin_log= 1;
if (opt_update_logname)
{
- // as opt_bin_log==0, no need to free opt_bin_logname
+ /* as opt_bin_log==0, no need to free opt_bin_logname */
if (!(opt_bin_logname= my_strdup(opt_update_logname, MYF(MY_WME))))
exit(EXIT_OUT_OF_MEMORY);
sql_print_error("The update log is no longer supported by MySQL in \
@@ -2718,8 +2718,8 @@ with --log-bin instead.");
}
if (opt_log_slave_updates && !opt_bin_log)
{
- sql_print_warning("You need to use --log-bin to make "
- "--log-slave-updates work.");
+ sql_print_warning("You need to use --log-bin to make "
+ "--log-slave-updates work.");
unireg_abort(1);
}
@@ -2781,7 +2781,15 @@ server.");
my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR));
opt_bin_logname=my_strdup(buf, MYF(0));
}
- mysql_bin_log.open_index_file(opt_binlog_index_name, ln);
+ if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln))
+ {
+ unireg_abort(1);
+ }
+
+ /*
+ Used to specify which type of lock we need to use for queries of type
+ INSERT ... SELECT. This will change when we have row level logging.
+ */
using_update_log=1;
}
@@ -2790,10 +2798,10 @@ server.");
sql_print_error("Can't init databases");
unireg_abort(1);
}
- tc_log= total_ha_2pc > 1 ? opt_bin_log ?
- (TC_LOG *)&mysql_bin_log :
- (TC_LOG *)&tc_log_mmap :
- (TC_LOG *)&tc_log_dummy;
+ tc_log= (total_ha_2pc > 1 ? (opt_bin_log ?
+ (TC_LOG *) &mysql_bin_log :
+ (TC_LOG *) &tc_log_mmap) :
+ (TC_LOG *) &tc_log_dummy);
if (tc_log->open(opt_bin_logname))
{
@@ -2808,7 +2816,7 @@ server.");
if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
WRITE_CACHE, 0, max_binlog_size, 0))
- unireg_abort(1);
+ unireg_abort(1);
#ifdef HAVE_REPLICATION
if (opt_bin_log && expire_logs_days)
@@ -3567,11 +3575,8 @@ inline void kill_broken_server()
(!opt_disable_networking && ip_sock == INVALID_SOCKET))
{
select_thread_in_use = 0;
-#ifdef __NETWARE__
- kill_server(MYSQL_KILL_SIGNAL); /* never returns */
-#else
- kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
-#endif /* __NETWARE__ */
+ /* The following call will never return */
+ kill_server(IF_NETWARE(MYSQL_KILL_SIGNAL, (void*) MYSQL_KILL_SIGNAL));
}
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
@@ -4170,6 +4175,7 @@ enum options_mysqld
OPT_INNODB_FAST_SHUTDOWN,
OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB,
OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
+ OPT_LOG_BIN_TRUST_ROUTINE_CREATORS,
OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG,
OPT_INNODB, OPT_ISAM,
OPT_ENGINE_CONDITION_PUSHDOWN,
@@ -4218,7 +4224,8 @@ enum options_mysqld
OPT_PRELOAD_BUFFER_SIZE,
OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
- OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
+ OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT,
+ OPT_RELAY_LOG_PURGE,
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
@@ -4510,12 +4517,7 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
".",
(gptr*) &innobase_fast_shutdown,
(gptr*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0,
-#ifndef __NETWARE__
- 2,
-#else
- 1,
-#endif
- 0, 0, 0},
+ IF_NETWARE(1,2), 0, 0, 0},
{"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
"Stores each InnoDB table to an .ibd file in the database dir.",
(gptr*) &innobase_file_per_table,
@@ -4590,6 +4592,17 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
"File that holds the names for last binary log files.",
(gptr*) &opt_binlog_index_name, (gptr*) &opt_binlog_index_name, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ /*
+ This option starts with "log-bin" to emphasize that it is specific of
+ binary logging. Hopefully in 5.1 nobody will need it anymore, when we have
+ row-level binlog.
+ */
+ {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_ROUTINE_CREATORS,
+ "If equal to 0 (the default), then when --log-bin is used, creation of "
+ "a routine is allowed only to users having the SUPER privilege and only"
+ "if this routine may not break binary logging",
+ (gptr*) &trust_routine_creators, (gptr*) &trust_routine_creators, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-error", OPT_ERROR_LOG_FILE, "Error log file.",
(gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR,
OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -5439,6 +5452,11 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.read_rnd_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ {"div_precision_increment", OPT_DIV_PRECINCREMENT,
+ "Precision of the result of '/' operator will be increased on that value.",
+ (gptr*) &global_system_variables.div_precincrement,
+ (gptr*) &max_system_variables.div_precincrement, 0, GET_ULONG,
+ REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
{"record_buffer", OPT_RECORD_BUFFER,
"Alias for read_buffer_size",
(gptr*) &global_system_variables.read_buff_size,
@@ -6972,9 +6990,15 @@ static void create_pid_file()
char buff[21], *end;
end= int10_to_str((long) getpid(), buff, 10);
*end++= '\n';
- (void) my_write(file, (byte*) buff, (uint) (end-buff),MYF(MY_WME));
+ if (!my_write(file, (byte*) buff, (uint) (end-buff), MYF(MY_WME | MY_NABP)))
+ {
+ (void) my_close(file, MYF(0));
+ return;
+ }
(void) my_close(file, MYF(0));
}
+ sql_perror("Can't start server: can't create PID file");
+ exit(1);
}
@@ -6989,5 +7013,4 @@ template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
template class I_List<NAMED_LIST>;
-FIX_GCC_LINKING_PROBLEM
#endif
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 4fbbeedb812..44539ec2d74 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -495,7 +495,7 @@ net_real_write(NET *net,const char *packet,ulong len)
thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff);
#else
alarmed=0;
- vio_timeout(net->vio, net->write_timeout);
+ vio_timeout(net->vio, 1, net->write_timeout);
#endif /* NO_ALARM */
pos=(char*) packet; end=pos+len;
@@ -688,7 +688,7 @@ my_real_read(NET *net, ulong *complen)
if (net_blocking)
thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
#else
- vio_timeout(net->vio, net->read_timeout);
+ vio_timeout(net->vio, 0, net->read_timeout);
#endif /* NO_ALARM */
pos = net->buff + net->where_b; /* net->packet -4 */
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 95fe003770b..b81a083d9b3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -853,7 +853,7 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
bool retrieve_full_rows,
MEM_ROOT *parent_alloc)
: cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows),
- scans_inited(false)
+ scans_inited(FALSE)
{
index= MAX_KEY;
head= table;
@@ -1022,7 +1022,7 @@ int QUICK_ROR_INTERSECT_SELECT::reset()
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset");
if (!scans_inited && init_ror_merged_scan(TRUE))
DBUG_RETURN(1);
- scans_inited= true;
+ scans_inited= TRUE;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
QUICK_RANGE_SELECT *quick;
while ((quick= it++))
@@ -1066,7 +1066,7 @@ QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT()
QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
TABLE *table)
- : thd(thd_param), scans_inited(false)
+ : thd(thd_param), scans_inited(FALSE)
{
index= MAX_KEY;
head= table;
@@ -1148,7 +1148,7 @@ int QUICK_ROR_UNION_SELECT::reset()
if (quick->init_ror_merged_scan(FALSE))
DBUG_RETURN(1);
}
- scans_inited= true;
+ scans_inited= TRUE;
}
queue_remove_all(&queue);
/*
@@ -2677,7 +2677,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
{
/* Don't add this scan if it doesn't improve selectivity. */
DBUG_PRINT("info", ("The scan doesn't improve selectivity."));
- DBUG_RETURN(false);
+ DBUG_RETURN(FALSE);
}
info->out_rows *= selectivity_mult;
@@ -2865,7 +2865,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
while (cur_ror_scan != tree->ror_scans_end && !intersect->is_covering)
{
/* S= S + first(R); R= R - first(R); */
- if (!ror_intersect_add(intersect, *cur_ror_scan, false))
+ if (!ror_intersect_add(intersect, *cur_ror_scan, FALSE))
{
cur_ror_scan++;
continue;
@@ -5513,14 +5513,26 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields)
}
-/****************************************************************************
- Create a QUICK RANGE based on a key
- This allocates things in a new memory root, as this may be called many times
- during a query.
-****************************************************************************/
+/*
+ Create quick select from ref/ref_or_null scan.
+ SYNOPSIS
+ get_quick_select_for_ref()
+ thd Thread handle
+ table Table to access
+ ref ref[_or_null] scan parameters
+ records Estimate of number of records (needed only to construct
+ quick select)
+ NOTES
+ This allocates things in a new memory root, as this may be called many
+ times during a query.
+
+ RETURN
+ Quick select that retrieves the same rows as passed ref scan
+ NULL on error.
+*/
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
- TABLE_REF *ref)
+ TABLE_REF *ref, ha_rows records)
{
MEM_ROOT *old_root= thd->mem_root;
/* The following call may change thd->mem_root */
@@ -5537,6 +5549,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
delete quick;
goto err;
}
+ quick->records= records;
if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error ||
!(range= new QUICK_RANGE()))
@@ -6657,6 +6670,8 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
- NGA = QA - (GA union C) = {NG_1, ..., NG_m} - the ones not in
GROUP BY and not referenced by MIN/MAX functions.
with the following properties specified below.
+ B3. If Q has a GROUP BY WITH ROLLUP clause the access method is not
+ applicable.
SA1. There is at most one attribute in SA referenced by any number of
MIN and/or MAX functions which, which if present, is denoted as C.
@@ -6741,6 +6756,8 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
other field as in: "select min(a) from t1 group by a" ?
- We assume that the general correctness of the GROUP-BY query was checked
before this point. Is this correct, or do we have to check it completely?
+ - Lift the limitation in condition (B3), that is, make this access method
+ applicable to ROLLUP queries.
RETURN
If mem_root != NULL
@@ -6780,7 +6797,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
DBUG_RETURN(NULL); /* This is not a select statement. */
if ((join->tables != 1) || /* The query must reference one table. */
((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
- (!join->select_distinct)))
+ (!join->select_distinct)) ||
+ (thd->lex->select_lex.olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
DBUG_RETURN(NULL);
if (table->s->keys == 0) /* There are no indexes to use. */
DBUG_RETURN(NULL);
@@ -8067,7 +8085,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
}
else
{
- /* Apply the constant equality conditions to the non-group select fields. */
+ /* Apply the constant equality conditions to the non-group select fields */
if (key_infix_len > 0)
{
if ((result= file->index_read(record, group_prefix, real_prefix_len,
@@ -8101,9 +8119,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
*/
if (!result)
{
- if(key_cmp(index_info->key_part, group_prefix, real_prefix_len))
+ if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
key_restore(record, tmp_record, index_info, 0);
- } else if (result == HA_ERR_KEY_NOT_FOUND)
+ }
+ else if (result == HA_ERR_KEY_NOT_FOUND)
result= 0; /* There is a result in any case. */
}
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 97d646cedbe..8d365262334 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -20,7 +20,7 @@
#ifndef _opt_range_h
#define _opt_range_h
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -281,7 +281,8 @@ protected:
friend class TRP_ROR_INTERSECT;
friend
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
- struct st_table_ref *ref);
+ struct st_table_ref *ref,
+ ha_rows records);
friend bool get_quick_keys(struct st_qsel_param *param,
QUICK_RANGE_SELECT *quick,KEY_PART *key,
SEL_ARG *key_tree,
@@ -709,5 +710,6 @@ public:
};
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
- struct st_table_ref *ref);
+ struct st_table_ref *ref,
+ ha_rows records);
#endif
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 134d3564ef8..ddeeb44c82b 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -313,7 +313,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
removed_tables is != 0 if we have used MIN() or MAX().
*/
if (removed_tables && used_tables != removed_tables)
- const_result= 0; // We didn't remove all tables
+ const_result= 0; // We didn't remove all tables
return const_result;
}
@@ -323,12 +323,14 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
SYNOPSIS
simple_pred()
- func_item in: Predicate item
+ func_item Predicate item
args out: Here we store the field followed by constants
- inv_order out: Is set to 1 if the predicate is of the form 'const op field'
+ inv_order out: Is set to 1 if the predicate is of the form
+ 'const op field'
RETURN
- 0 func_item is a simple predicate: a field is compared with constants
+ 0 func_item is a simple predicate: a field is compared with
+ constants
1 Otherwise
*/
diff --git a/sql/procedure.h b/sql/procedure.h
index 5d0dccbcd5e..aceadd10883 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -17,7 +17,7 @@
/* When using sql procedures */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 2ea435d84ef..9a96da004c5 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -820,7 +820,7 @@ bool Protocol_simple::store_long(longlong from)
#endif
char buff[20];
return net_store_data((char*) buff,
- (uint) (int10_to_str((int)from,buff, (from <0)?-10:10)-buff));
+ (uint) (int10_to_str((long int)from,buff, (from <0)?-10:10)-buff));
}
diff --git a/sql/protocol.h b/sql/protocol.h
index de379db541b..01331ef64ba 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 0e6e36f63a2..4add5d6b39b 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -203,6 +203,9 @@ sys_var_key_cache_long sys_key_cache_age_threshold("key_cache_age_threshold",
param_age_threshold));
sys_var_bool_ptr sys_local_infile("local_infile",
&opt_local_infile);
+sys_var_bool_ptr
+sys_trust_routine_creators("log_bin_trust_routine_creators",
+ &trust_routine_creators);
sys_var_thd_ulong sys_log_warnings("log_warnings", &SV::log_warnings);
sys_var_thd_ulong sys_long_query_time("long_query_time",
&SV::long_query_time);
@@ -295,6 +298,8 @@ sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size);
+sys_var_thd_ulong sys_div_precincrement("div_precision_increment",
+ &SV::div_precincrement);
#ifdef HAVE_REPLICATION
sys_var_bool_ptr sys_relay_log_purge("relay_log_purge",
&relay_log_purge);
@@ -567,6 +572,7 @@ sys_var *sys_variables[]=
&sys_connect_timeout,
&sys_date_format,
&sys_datetime_format,
+ &sys_div_precincrement,
&sys_default_week_format,
&sys_delay_key_write,
&sys_delayed_insert_limit,
@@ -703,6 +709,7 @@ sys_var *sys_variables[]=
&sys_innodb_thread_sleep_delay,
&sys_innodb_thread_concurrency,
#endif
+ &sys_trust_routine_creators,
&sys_engine_condition_pushdown,
#ifdef HAVE_NDBCLUSTER_DB
&sys_ndb_autoincrement_prefetch_sz,
@@ -754,6 +761,7 @@ struct show_var_st init_vars[]= {
{"datadir", mysql_real_data_home, SHOW_CHAR},
{sys_date_format.name, (char*) &sys_date_format, SHOW_SYS},
{sys_datetime_format.name, (char*) &sys_datetime_format, SHOW_SYS},
+ {sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
{sys_default_week_format.name, (char*) &sys_default_week_format, SHOW_SYS},
{sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS},
{sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
@@ -842,6 +850,7 @@ struct show_var_st init_vars[]= {
#endif
{"log", (char*) &opt_log, SHOW_BOOL},
{"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
+ {sys_trust_routine_creators.name,(char*) &sys_trust_routine_creators, SHOW_SYS},
{"log_error", (char*) log_error_file, SHOW_CHAR},
#ifdef HAVE_REPLICATION
{"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_MY_BOOL},
diff --git a/sql/set_var.h b/sql/set_var.h
index 585f6df3547..32f45187124 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -16,7 +16,7 @@
/* Classes to support the SET command */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
index 3c35ec98a92..a6bb4bad99b 100644
--- a/sql/share/charsets/Index.xml
+++ b/sql/share/charsets/Index.xml
@@ -367,6 +367,9 @@ To make maintaining easier please:
<order>Slovenian</order>
<order>Sorbian</order>
</collation>
+ <collation name="cp1250_croatian_ci" id="44">
+ <order>Croatian</order>
+ </collation>
<collation name="cp1250_czech_cs" id="34" order="Czech">
<flag>compiled</flag>
</collation>
diff --git a/sql/share/charsets/cp1250.xml b/sql/share/charsets/cp1250.xml
index 8e7102b6737..1e62e64ad5a 100644
--- a/sql/share/charsets/cp1250.xml
+++ b/sql/share/charsets/cp1250.xml
@@ -57,7 +57,7 @@
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 81 82 83 84 85 86 87 88 89 9A 8B 9C 9D 9E 9F
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
- A0 A1 A2 B3 A4 B9 A6 DF A8 A9 BA AB AC AD AE BF
+ A0 A1 A2 B3 A4 B9 A6 A7 A8 A9 BA AB AC AD AE BF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BE BD BE BF
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
@@ -82,7 +82,7 @@
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
B0 B1 B2 A3 B4 B5 B6 B7 B8 A5 AA BB BC BD BC AF
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE A7
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
</map>
@@ -132,6 +132,27 @@
</map>
</collation>
+<collation name="cp1250_croatian_ci">
+<map>
+00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+40 41 43 44 48 4B 4D 4E 4F 50 52 53 54 56 57 59
+5B 5C 5D 5F 62 64 66 67 68 69 6B 90 91 92 93 94
+95 41 43 44 48 4B 4D 4E 4F 50 52 53 54 56 57 59
+5B 5C 5D 5F 62 64 66 67 68 69 6B 96 97 98 99 9A
+9B 9C 9E 9F A0 A1 A2 A3 A4 A5 60 A6 5F 62 6C 6B
+A7 A8 A9 AA AB AC AD AE AF B0 60 B1 5F 62 6C 6B
+B2 B3 B4 54 B5 41 B6 B7 B8 B9 5F BA BB BC BD 6B
+BE BF C0 54 C1 C2 C3 C4 C5 41 5F C6 54 C7 54 6B
+5D 41 41 41 41 54 47 44 46 4B 4B 4B 4B 50 50 48
+4A 57 57 59 59 59 59 C8 5D 64 64 64 64 69 62 5F
+5D 41 41 41 41 54 47 44 46 4B 4B 4B 4B 50 50 48
+4A 57 57 59 59 59 59 C9 5D 64 64 64 64 69 62 FF
+</map>
+</collation>
+
<collation name="cp1250_czech_ci"/>
<collation name="cp1250_bin" flag="binary"/>
diff --git a/sql/share/charsets/latin2.xml b/sql/share/charsets/latin2.xml
index 702f052604b..7f00148a1df 100644
--- a/sql/share/charsets/latin2.xml
+++ b/sql/share/charsets/latin2.xml
@@ -60,7 +60,7 @@
A0 B1 A2 B3 A4 B5 B6 A7 A8 B9 BA BB BC AD BE BF
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
- D0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
+ F0 F1 F2 F3 F4 F5 F6 D7 F8 F9 FA FB FC FD FE DF
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
</map>
@@ -84,7 +84,7 @@
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
- F0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
+ D0 D1 D2 D3 D4 D5 D6 F7 D8 D9 DA DB DC DD DE FF
</map>
</upper>
@@ -135,22 +135,22 @@
<collation name="latin2_croatian_ci">
<map>
- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
- 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
- 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- 40 41 42 43 46 48 49 4A 4B 4C 4D 4E 4F 50 51 52
- 53 54 55 56 58 59 5A 5B 5C 5D 5E 5B 5C 5D 5E 5F
- 60 41 42 43 46 48 49 4A 4B 4C 4D 4E 4F 50 51 52
- 53 54 55 56 58 59 5A 5B 5C 5D 5E 7B 7C 7D 7E 7F
- 80 81 82 83 84 85 86 87 88 89 57 8B 8C 8D 5F 8F
- 90 91 92 93 94 95 96 97 98 99 57 9B 9C 9D 5F 9F
- A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
- B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
- 41 41 41 41 5C 5B 45 43 44 45 45 45 49 49 49 49
- 47 4E 4F 4F 4F 4F 5D D7 D8 55 55 55 59 59 DE DF
- 41 41 41 41 5C 5B 45 43 44 45 45 45 49 49 49 49
- 47 4E 4F 4F 4F 4F 5D F7 D8 55 55 55 59 59 DE FF
+00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+40 41 43 44 48 4B 4D 4E 4F 50 52 53 54 56 57 59
+5B 5C 5D 5F 62 64 66 67 68 69 6B C6 C7 C8 C9 CA
+CB 41 43 44 48 4B 4D 4E 4F 50 52 53 54 56 57 59
+5B 5C 5D 5F 62 64 66 67 68 69 6B CC CD CE CF D0
+D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0
+E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0
+F1 41 F2 54 F3 54 5F F4 F5 61 5F 62 6B F6 8E 6B
+F7 41 F8 54 F9 54 5F FA FB 61 5F 62 6B FC 8E 6B
+5D 41 41 41 41 54 47 44 46 4B 4B 4B 4B 50 50 48
+4A 57 57 59 59 59 59 FD 5D 64 64 64 64 69 62 5F
+5D 41 41 41 41 54 47 44 46 4B 4B 4B 4B 50 50 48
+4A 57 57 59 59 59 59 FE 5D 64 64 64 64 69 62 FF
</map>
</collation>
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 3a311ff7917..848cc422dc2 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -4766,13 +4766,13 @@ ER_SUBQUERY_NO_1_ROW 21000
swe "Subquery returnerade mer än 1 rad"
ukr "ð¦ÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ¦ÌØÛ ÎiÖ 1 ÚÁÐÉÓ"
ER_UNKNOWN_STMT_HANDLER
- dan "Unknown prepared statement handler (%ld) given to %s"
+ dan "Unknown prepared statement handler (%.*s) given to %s"
eng "Unknown prepared statement handler (%.*s) given to %s"
ger "Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben"
por "Desconhecido manipulador de declaração preparado (%.*s) determinado para %s"
- spa "Desconocido preparado comando handler (%ld) dado para %s"
- swe "Okänd PREPARED STATEMENT id (%ld) var given till %s"
- ukr "Unknown prepared statement handler (%ld) given to %s"
+ spa "Desconocido preparado comando handler (%.*s) dado para %s"
+ swe "Okänd PREPARED STATEMENT id (%.*s) var given till %s"
+ ukr "Unknown prepared statement handler (%.*s) given to %s"
ER_CORRUPT_HELP_DB
eng "Help database is corrupt or does not exist"
ger "Die Hilfe-Datenbank ist beschädigt oder existiert nicht"
@@ -5344,3 +5344,15 @@ ER_SP_NOT_VAR_ARG 42000
eng "OUT or INOUT argument %d for routine %s is not a variable"
ER_SP_NO_RETSET_IN_FUNC 0A000
eng "Not allowed to return a result set from a function"
+ER_CANT_CREATE_GEOMETRY_OBJECT 22003
+ eng "Cannot get geometry object from data you send to the GEOMETRY field"
+ER_FAILED_ROUTINE_BREAK_BINLOG
+ eng "A routine failed and is declared to modify data and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes"
+ER_BINLOG_UNSAFE_ROUTINE
+ eng "This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
+ER_BINLOG_CREATE_ROUTINE_NEED_SUPER
+ eng "You do not have SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)"
+ER_EXEC_STMT_WITH_OPEN_CURSOR
+ eng "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it."
+ER_STMT_HAS_NO_OPEN_CURSOR
+ eng "The statement (%d) has no open cursor."
diff --git a/sql/slave.cc b/sql/slave.cc
index ebf87660a0e..70803c88c3a 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -852,7 +852,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
SYNOPSIS
tables_ok()
- thd thread (SQL slave thread normally)
+ thd thread (SQL slave thread normally). Mustn't be null.
tables list of tables to check
NOTES
@@ -885,6 +885,23 @@ bool tables_ok(THD* thd, TABLE_LIST* tables)
bool some_tables_updating= 0;
DBUG_ENTER("tables_ok");
+ /*
+ In routine, can't reliably pick and choose substatements, so always
+ replicate.
+ We can't reliably know if one substatement should be executed or not:
+ consider the case of this substatement: a SELECT on a non-replicated
+ constant table; if we don't execute it maybe it was going to fill a
+ variable which was going to be used by the next substatement to update
+ a replicated table? If we execute it maybe the constant non-replicated
+ table does not exist (and so we'll fail) while there was no need to
+ execute this as this SELECT does not influence replicated tables in the
+ rest of the routine? In other words: users are used to replicate-*-table
+ specifying how to handle updates to tables, these options don't say
+ anything about reads to tables; we can't guess.
+ */
+ if (thd->spcont)
+ DBUG_RETURN(1);
+
for (; tables; tables= tables->next_global)
{
char hash_key[2*NAME_LEN+2];
@@ -2791,12 +2808,17 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
DBUG_ENTER("init_slave_thread");
thd->system_thread = (thd_type == SLAVE_THD_SQL) ?
SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
+ /*
+ The two next lines are needed for replication of SP (CREATE PROCEDURE
+ needs a valid user to store in mysql.proc).
+ */
+ thd->priv_user= (char *) "";
+ thd->priv_host[0]= '\0';
thd->host_or_ip= "";
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
thd->net.read_timeout = slave_net_timeout;
thd->master_access= ~0;
- thd->priv_user = 0;
thd->slave_thread = 1;
set_slave_thread_options(thd);
/*
diff --git a/sql/sp.cc b/sql/sp.cc
index 1956f32f2c6..81513cb3198 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -58,6 +58,9 @@ enum
bool mysql_proc_table_exists= 1;
+/* Tells what SP_DEFAULT_ACCESS should be mapped to */
+#define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL
+
/* *opened=true means we opened ourselves */
static int
db_find_routine_aux(THD *thd, int type, sp_name *name,
@@ -189,7 +192,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
chistics.daccess= SP_MODIFIES_SQL_DATA;
break;
default:
- chistics.daccess= SP_CONTAINS_SQL;
+ chistics.daccess= SP_DEFAULT_ACCESS_MAPPING;
}
if ((ptr= get_field(thd->mem_root,
@@ -425,9 +428,46 @@ db_create_routine(THD *thd, int type, sp_head *sp)
store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
system_charset_info);
+ if (!trust_routine_creators && mysql_bin_log.is_open())
+ {
+ if (!sp->m_chistics->detistic)
+ {
+ /*
+ Note that for a _function_ this test is not enough; one could use
+ a non-deterministic read-only function in an update statement.
+ */
+ enum enum_sp_data_access access=
+ (sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
+ SP_DEFAULT_ACCESS_MAPPING : sp->m_chistics->daccess;
+ if (access == SP_CONTAINS_SQL ||
+ access == SP_MODIFIES_SQL_DATA)
+ {
+ my_message(ER_BINLOG_UNSAFE_ROUTINE,
+ ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
+ ret= SP_INTERNAL_ERROR;
+ goto done;
+ }
+ }
+ if (!(thd->master_access & SUPER_ACL))
+ {
+ my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
+ ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0));
+ ret= SP_INTERNAL_ERROR;
+ goto done;
+ }
+ }
+
ret= SP_OK;
if (table->file->write_row(table->record[0]))
ret= SP_WRITE_ROW_FAILED;
+ else if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ /* Such a statement can always go directly to binlog, no trans cache */
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
}
done:
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index ad14116a4c7..2ffcd45b1a7 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -97,19 +97,48 @@ sp_multi_results_command(enum enum_sql_command cmd)
}
}
+
+/*
+ Prepare Item for execution (call of fix_fields)
+
+ SYNOPSIS
+ sp_prepare_func_item()
+ thd thread handler
+ it_addr pointer on item refernce
+
+ RETURN
+ NULL error
+ prepared item
+*/
+
+static Item *
+sp_prepare_func_item(THD* thd, Item **it_addr)
+{
+ Item *it= *it_addr;
+ DBUG_ENTER("sp_prepare_func_item");
+ it_addr= it->this_item_addr(thd, it_addr);
+
+ if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr))
+ {
+ DBUG_PRINT("info", ("fix_fields() failed"));
+ DBUG_RETURN(NULL);
+ }
+ DBUG_RETURN(*it_addr);
+}
+
+
/* Evaluate a (presumed) func item. Always returns an item, the parameter
** if nothing else.
*/
Item *
-sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
+sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type)
{
DBUG_ENTER("sp_eval_func_item");
- it= it->this_item();
+ Item *it= sp_prepare_func_item(thd, it_addr);
DBUG_PRINT("info", ("type: %d", type));
- if (!it->fixed && it->fix_fields(thd, 0, &it))
+ if (!it)
{
- DBUG_PRINT("info", ("fix_fields() failed"));
DBUG_RETURN(NULL);
}
@@ -164,7 +193,10 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
it= new Item_null();
else
it= new Item_decimal(val);
- dbug_print_decimal("info", "DECIMAL_RESULT: %s", val);
+#ifndef DBUG_OFF
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ DBUG_PRINT("info", ("DECIMAL_RESULT: %s", dbug_decimal_as_string(dbug_buff, val)));
+#endif
break;
}
case STRING_RESULT:
@@ -382,32 +414,33 @@ sp_head::create_typelib(List<String> *src)
return 0;
result->type_lengths= (unsigned int *)(result->type_names + result->count+1);
List_iterator<String> it(*src);
- String conv, *tmp;
- uint32 dummy;
- for (uint i=0; i<result->count; i++)
+ String conv;
+ for (uint i=0; i < result->count; i++)
{
- tmp = it++;
+ uint32 dummy;
+ uint length;
+ String *tmp= it++;
+
if (String::needs_conversion(tmp->length(), tmp->charset(),
cs, &dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
- char *buf= (char*) alloc_root(mem_root,conv.length()+1);
- memcpy(buf, conv.ptr(), conv.length());
- buf[conv.length()]= '\0';
- result->type_names[i]= buf;
- result->type_lengths[i]= conv.length();
+
+ length= conv.length();
+ result->type_names[i]= (char*) strmake_root(mem_root, conv.ptr(),
+ length);
}
- else {
- result->type_names[i]= strdup_root(mem_root, tmp->c_ptr());
- result->type_lengths[i]= tmp->length();
+ else
+ {
+ length= tmp->length();
+ result->type_names[i]= strmake_root(mem_root, tmp->ptr(), length);
}
// Strip trailing spaces.
- uint lengthsp= cs->cset->lengthsp(cs, result->type_names[i],
- result->type_lengths[i]);
- result->type_lengths[i]= lengthsp;
- ((uchar *)result->type_names[i])[lengthsp]= '\0';
+ length= cs->cset->lengthsp(cs, result->type_names[i], length);
+ result->type_lengths[i]= length;
+ ((uchar *)result->type_names[i])[length]= '\0';
}
result->type_names[result->count]= 0;
result->type_lengths[result->count]= 0;
@@ -675,7 +708,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
for (i= 0 ; i < params && i < argcount ; i++)
{
sp_pvar_t *pvar = m_pcont->find_pvar(i);
- Item *it= sp_eval_func_item(thd, *argp++, pvar->type);
+ Item *it= sp_eval_func_item(thd, argp++, pvar->type);
if (it)
nctx->push_item(it);
@@ -757,7 +790,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
{
Item_null *nit= NULL; // Re-use this, and only create if needed
uint i;
- List_iterator_fast<Item> li(*args);
+ List_iterator<Item> li(*args);
Item *it;
nctx= new sp_rcontext(csize, hmax, cmax);
@@ -790,7 +823,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
}
else
{
- Item *it2= sp_eval_func_item(thd, it, pvar->type);
+ Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type);
if (it2)
nctx->push_item(it2); // IN or INOUT
@@ -1435,7 +1468,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
Item *it;
int res;
- it= sp_eval_func_item(thd, m_value, m_type);
+ it= sp_eval_func_item(thd, &m_value, m_type);
if (! it)
res= -1;
else
@@ -1565,13 +1598,13 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp)
Item *it;
int res;
- it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
+ it= sp_prepare_func_item(thd, &m_expr);
if (!it)
res= -1;
else
{
res= 0;
- if (it->val_int())
+ if (it->val_bool())
*nextp = m_dest;
else
*nextp = m_ip+1;
@@ -1623,13 +1656,13 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
Item *it;
int res;
- it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
+ it= sp_prepare_func_item(thd, &m_expr);
if (! it)
res= -1;
else
{
res= 0;
- if (! it->val_int())
+ if (! it->val_bool())
*nextp = m_dest;
else
*nextp = m_ip+1;
@@ -1681,7 +1714,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
Item *it;
int res;
- it= sp_eval_func_item(thd, m_value, m_type);
+ it= sp_eval_func_item(thd, &m_value, m_type);
if (! it)
res= -1;
else
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index def38009eee..672491a97f2 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -41,10 +41,10 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax)
}
int
-sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type)
+sp_rcontext::set_item_eval(uint idx, Item **item_addr, enum_field_types type)
{
- extern Item *sp_eval_func_item(THD *thd, Item *it, enum_field_types type);
- Item *it= sp_eval_func_item(current_thd, i, type);
+ extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type);
+ Item *it= sp_eval_func_item(current_thd, item_addr, type);
if (! it)
return -1;
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index afcd937a369..c132032e32c 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -74,7 +74,7 @@ class sp_rcontext : public Sql_alloc
/* Returns 0 on success, -1 on (eval) failure */
int
- set_item_eval(uint idx, Item *i, enum_field_types type);
+ set_item_eval(uint idx, Item **i, enum_field_types type);
inline Item *
get_item(uint idx)
@@ -82,6 +82,14 @@ class sp_rcontext : public Sql_alloc
return m_frame[idx];
}
+
+ inline Item **
+ get_item_addr(uint idx)
+ {
+ return m_frame + idx;
+ }
+
+
inline void
set_result(Item *it)
{
diff --git a/sql/spatial.cc b/sql/spatial.cc
index bcfefd9dde8..427648850e4 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -22,6 +22,8 @@
/***************************** Gis_class_info *******************************/
+String Geometry::bad_geometry_data("Bad object", &my_charset_bin);
+
Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_end+1]=
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL
diff --git a/sql/spatial.h b/sql/spatial.h
index b96434831a1..438ec171a72 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -173,6 +173,8 @@ public:
static void operator delete(void *ptr, void *buffer)
{}
+ static String bad_geometry_data;
+
enum wkbType
{
wkb_point= 1,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index df19c6e55fd..ca9ba7611e6 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -63,8 +63,7 @@ static bool allow_all_hosts=1;
static HASH acl_check_hosts, column_priv_hash, proc_priv_hash;
static DYNAMIC_ARRAY acl_wild_hosts;
static hash_filo *acl_cache;
-static uint grant_version=0;
-static uint priv_version=0; /* Version of priv tables. incremented by acl_init */
+static uint grant_version=0; /* Version of priv tables. incremented by acl_init */
static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...);
@@ -153,7 +152,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
DBUG_RETURN(0); /* purecov: tested */
}
- priv_version++; /* Privileges updated */
+ grant_version++; /* Privileges updated */
mysql_proc_table_exists= 1; // Assume mysql.proc exists
/*
@@ -1515,7 +1514,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
*/
tables.updating= 1;
/* Thanks to bzero, tables.next==0 */
- if (!tables_ok(0, &tables))
+ if (!tables_ok(thd, &tables))
DBUG_RETURN(0);
}
#endif
@@ -2173,10 +2172,14 @@ static int replace_column_table(GRANT_TABLE *g_t,
KEY_PART_INFO *key_part= table->key_info->key_part;
DBUG_ENTER("replace_column_table");
- table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
- table->field[1]->store(db,(uint) strlen(db), system_charset_info);
- table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
- table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info);
+ table->field[0]->store(combo.host.str,combo.host.length,
+ system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db),
+ system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length,
+ system_charset_info);
+ table->field[3]->store(table_name,(uint) strlen(table_name),
+ system_charset_info);
/* Get length of 3 first key parts */
key_prefix_length= (key_part[0].store_length + key_part[1].store_length +
@@ -2188,17 +2191,17 @@ static int replace_column_table(GRANT_TABLE *g_t,
/* first fix privileges for all columns in column list */
List_iterator <LEX_COLUMN> iter(columns);
- class LEX_COLUMN *xx;
+ class LEX_COLUMN *column;
table->file->ha_index_init(0);
- while ((xx=iter++))
+ while ((column= iter++))
{
- ulong privileges = xx->rights;
+ ulong privileges= column->rights;
bool old_row_exists=0;
byte user_key[MAX_KEY_LENGTH];
key_restore(table->record[0],key,table->key_info,
key_prefix_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length(),
+ table->field[4]->store(column->column.ptr(), column->column.length(),
system_charset_info);
/* Get key for the first 4 columns */
key_copy(user_key, table->record[0], table->key_info,
@@ -2213,15 +2216,15 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
combo.user.str, combo.host.str,
- table_name); /* purecov: inspected */
- result= -1; /* purecov: inspected */
- continue; /* purecov: inspected */
+ table_name); /* purecov: inspected */
+ result= -1; /* purecov: inspected */
+ continue; /* purecov: inspected */
}
old_row_exists = 0;
restore_record(table, s->default_values); // Get empty record
key_restore(table->record[0],key,table->key_info,
key_prefix_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length(),
+ table->field[4]->store(column->column.ptr(),column->column.length(),
system_charset_info);
}
else
@@ -2241,6 +2244,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
if (old_row_exists)
{
+ GRANT_COLUMN *grant_column;
if (privileges)
error=table->file->update_row(table->record[1],table->record[0]);
else
@@ -2251,21 +2255,21 @@ static int replace_column_table(GRANT_TABLE *g_t,
result= -1; /* purecov: inspected */
goto end; /* purecov: inspected */
}
- GRANT_COLUMN *grant_column = column_hash_search(g_t,
- xx->column.ptr(),
- xx->column.length());
+ grant_column= column_hash_search(g_t, column->column.ptr(),
+ column->column.length());
if (grant_column) // Should always be true
- grant_column->rights = privileges; // Update hash
+ grant_column->rights= privileges; // Update hash
}
else // new grant
{
+ GRANT_COLUMN *grant_column;
if ((error=table->file->write_row(table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
result= -1; /* purecov: inspected */
goto end; /* purecov: inspected */
}
- GRANT_COLUMN *grant_column = new GRANT_COLUMN(xx->column,privileges);
+ grant_column= new GRANT_COLUMN(column->column,privileges);
my_hash_insert(&g_t->hash_columns,(byte*) grant_column);
}
}
@@ -2699,7 +2703,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
account in tests.
*/
tables[0].updating= tables[1].updating= tables[2].updating= 1;
- if (!tables_ok(0, tables))
+ if (!tables_ok(thd, tables))
DBUG_RETURN(FALSE);
}
#endif
@@ -2716,6 +2720,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
rw_wrlock(&LOCK_grant);
MEM_ROOT *old_root= thd->mem_root;
thd->mem_root= &memex;
+ grant_version++;
while ((Str = str_list++))
{
@@ -2904,7 +2909,7 @@ bool mysql_procedure_grant(THD *thd, TABLE_LIST *table_list,
account in tests.
*/
tables[0].updating= tables[1].updating= 1;
- if (!tables_ok(0, tables))
+ if (!tables_ok(thd, tables))
DBUG_RETURN(FALSE);
}
#endif
@@ -3035,7 +3040,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
account in tests.
*/
tables[0].updating= tables[1].updating= 1;
- if (!tables_ok(0, tables))
+ if (!tables_ok(thd, tables))
DBUG_RETURN(FALSE);
}
#endif
@@ -3684,9 +3689,9 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant,
grant_column= column_hash_search(grant_table, field_name,
(uint) strlen(field_name));
if (!grant_column)
- priv= grant->privilege;
+ priv= (grant->privilege | grant_table->privs);
else
- priv= grant->privilege | grant_column->rights;
+ priv= (grant->privilege | grant_table->privs | grant_column->rights);
}
rw_unlock(&LOCK_grant);
return priv;
@@ -4245,7 +4250,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
*/
tables[0].updating=tables[1].updating=tables[2].updating=
tables[3].updating=tables[4].updating=1;
- if (!tables_ok(0, tables))
+ if (!tables_ok(thd, tables))
DBUG_RETURN(1);
tables[0].updating=tables[1].updating=tables[2].updating=
tables[3].updating=tables[4].updating=0;;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index d79811aa4e2..bda5700b273 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1488,6 +1488,7 @@ bool wait_for_tables(THD *thd)
{
/* Now we can open all tables without any interference */
thd->proc_info="Reopen tables";
+ thd->version= refresh_version;
result=reopen_tables(thd,0,0);
}
pthread_mutex_unlock(&LOCK_open);
@@ -2689,6 +2690,17 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{
if (found == WRONG_GRANT)
return (Field*) 0;
+ {
+ SELECT_LEX *current_sel= thd->lex->current_select;
+ SELECT_LEX *last_select= item->cached_table->select_lex;
+ /*
+ If the field was an outer referencee, mark all selects using this
+ sub query as dependent of the outer query
+ */
+ if (current_sel != last_select)
+ mark_select_range_as_dependent(thd, last_select, current_sel,
+ found, *ref, item);
+ }
return found;
}
}
@@ -3157,10 +3169,8 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
{
for (TABLE_LIST *table= tables; table; table= table->next_local)
{
- if (table->view && !table->table)
+ if (table->view && table->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
- /* it is for multi table views only, check it */
- DBUG_ASSERT(table->ancestor->next_local != 0);
list= make_leaves_list(list, table->ancestor);
}
else
@@ -3858,11 +3868,8 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
TABLE *table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
- if ((value->save_in_field(field, 0) < 0) && !ignore_errors)
- {
- my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+ if (value->save_in_field(field, 0) == -1)
DBUG_RETURN(TRUE);
- }
}
DBUG_RETURN(thd->net.report_error);
}
diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h
index 5c51f3ecb67..2fd603d9381 100644
--- a/sql/sql_bitmap.h
+++ b/sql/sql_bitmap.h
@@ -91,7 +91,7 @@ template <> class Bitmap<64>
ulonglong map;
public:
Bitmap<64>() { }
-#if defined(__NETWARE__)
+#if defined(__NETWARE__) || defined(__MWERKS__)
/*
Metwork compiler gives error on Bitmap<64>
Changed to Bitmap, since in this case also it will proper construct
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 4a4f61f985c..430e0fbcabf 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1950,6 +1950,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
type = Query_cache_block::RES_CONT;
} while (block != *result_block);
#else
+ /*
+ Set type of first block, emb_store_querycache_result() will handle
+ the others.
+ */
+ (*result_block)->type= type;
Querycache_stream qs(*result_block, headers_len);
emb_store_querycache_result(&qs, (THD*)data);
#endif /*!EMBEDDED_LIBRARY*/
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index a6a1f4d60ef..2d5c4722164 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1719,10 +1719,9 @@ bool select_dumpvar::send_data(List<Item> &items)
List_iterator_fast<Item_func_set_user_var> li(vars);
List_iterator_fast<Item_splocal> var_li(local_vars);
List_iterator_fast<my_var> my_li(var_list);
- List_iterator_fast<Item> it(items);
+ List_iterator<Item> it(items);
Item_func_set_user_var *xx;
Item_splocal *yy;
- Item *item;
my_var *zz;
DBUG_ENTER("send_data");
if (unit->offset_limit_cnt)
@@ -1741,13 +1740,13 @@ bool select_dumpvar::send_data(List<Item> &items)
my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
DBUG_RETURN(1);
}
- while ((zz=my_li++) && (item=it++))
+ while ((zz=my_li++) && (it++))
{
if (zz->local)
{
if ((yy=var_li++))
{
- if (thd->spcont->set_item_eval(yy->get_offset(), item, zz->type))
+ if (thd->spcont->set_item_eval(yy->get_offset(), it.ref(), zz->type))
DBUG_RETURN(1);
}
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 62cee00043b..211648e63f7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -17,7 +17,7 @@
/* Classes in mysql */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -523,6 +523,7 @@ struct system_variables
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
+ ulong div_precincrement;
ulong sortbuff_size;
ulong table_type;
ulong tmp_table_size;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index d524bbcf164..cded9e2a13e 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -46,8 +46,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
DBUG_RETURN(TRUE);
if (!(table= table_list->table))
{
- DBUG_ASSERT(table_list->view &&
- table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(-1);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ac8f5a06745..adb33af05b9 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -81,15 +81,13 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
{
if (!table)
{
- DBUG_ASSERT(table_list->view &&
- table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
table_list->view_db.str, table_list->view_name.str);
return -1;
}
if (values.elements != table->s->fields)
{
- my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
return -1;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -112,7 +110,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
int res;
if (fields.elements != values.elements)
{
- my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
return -1;
}
@@ -125,7 +123,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
thd->lex->select_lex.no_wrap_view_item= 0;
if (res)
return -1;
- if (table == 0)
+ if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
/* it is join view => we need to find table for update */
List_iterator_fast<Item> it(fields);
@@ -135,7 +133,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
while ((item= it++))
map|= item->used_tables();
- if (table_list->check_single_table(&tbl, map) || tbl == 0)
+ if (table_list->check_single_table(&tbl, map, table_list) || tbl == 0)
{
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
table_list->view_db.str, table_list->view_name.str);
@@ -709,8 +707,6 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
thd->lex->empty_field_list_on_rset= 1;
if (!table_list->table)
{
- DBUG_ASSERT(table_list->view &&
- table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
@@ -897,7 +893,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
goto err;
if ((error=table->file->update_row(table->record[1],table->record[0])))
+ {
+ if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore)
+ break;
goto err;
+ }
info->updated++;
break;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 94f1a8e0df4..a33d60df0d4 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -296,7 +296,7 @@ protected:
*link_next, **link_prev; /* list of whole SELECT_LEX */
public:
- ulong options;
+ ulonglong options;
/*
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 55d9d668bdd..ac0f7f7012a 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 0cb3a1cbc11..47ac8d3afc1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -506,7 +506,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
uc->user_resources.conn_per_hour <= uc->conn_per_hour)
{
net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
- "max_connections",
+ "max_connections_per_hour",
(long) uc->user_resources.conn_per_hour);
error=1;
goto end;
@@ -1051,7 +1051,7 @@ pthread_handler_decl(handle_one_connection,arg)
/* now that we've called my_thread_init(), it is safe to call DBUG_* */
#if defined(__WIN__)
- init_signals(); // IRENA; testing ?
+ init_signals();
#elif !defined(OS2) && !defined(__NETWARE__)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
@@ -1433,9 +1433,6 @@ bool do_command(THD *thd)
}
else
{
- if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
- thd->killed= THD::NOT_KILLED;
-
packet=(char*) net->read_pos;
command = (enum enum_server_command) (uchar) packet[0];
if (command >= COM_END)
@@ -1482,6 +1479,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
bool error= 0;
DBUG_ENTER("dispatch_command");
+ if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
+ thd->killed= THD::NOT_KILLED;
+
thd->command=command;
/*
Commands which will always take a long time should be marked with
@@ -1764,7 +1764,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->lex->
select_lex.table_list.link_in_list((byte*) &table_list,
(byte**) &table_list.next_local);
- thd->lex->query_tables= &table_list;
+ thd->lex->add_to_query_tables(&table_list);
/* switch on VIEW optimisation: do not fill temporary tables */
thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
@@ -4097,7 +4097,43 @@ unsent_create_error:
thd->variables.select_limit= HA_POS_ERROR;
thd->row_count_func= 0;
+ tmp_disable_binlog(thd); /* don't binlog the substatements */
res= sp->execute_procedure(thd, &lex->value_list);
+ reenable_binlog(thd);
+
+ /*
+ We write CALL to binlog; on the opposite we didn't write the
+ substatements. That choice is necessary because the substatements
+ may use local vars.
+ Binlogging should happen when all tables are locked. They are locked
+ just above, and unlocked by close_thread_tables(). All tables which
+ are to be updated are locked like with a table-level write lock, and
+ this also applies to InnoDB (I tested - note that it reduces
+ InnoDB's concurrency as we don't use row-level locks). So binlogging
+ below is safe.
+ Note the limitation: if the SP returned an error, but still did some
+ updates, we do NOT binlog it. This is because otherwise "permission
+ denied", "table does not exist" etc would stop the slave quite
+ often. There is no easy way to know if the SP updated something
+ (even no_trans_update is not suitable, as it may be a transactional
+ autocommit update which happened, and no_trans_update covers only
+ INSERT/UPDATE/LOAD).
+ */
+ if (mysql_bin_log.is_open() &&
+ (sp->m_chistics->daccess == SP_CONTAINS_SQL ||
+ sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
+ {
+ if (res)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_FAILED_ROUTINE_BREAK_BINLOG,
+ ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
+ else
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
/*
If warnings have been cleared, we have to clear total_warn_count
@@ -4153,14 +4189,32 @@ unsent_create_error:
sp->m_name.str, 0))
goto error;
memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
- if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
- result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
- else
- result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
+ if (!trust_routine_creators && mysql_bin_log.is_open() &&
+ !sp->m_chistics->detistic &&
+ (chistics.daccess == SP_CONTAINS_SQL ||
+ chistics.daccess == SP_MODIFIES_SQL_DATA))
+ {
+ my_message(ER_BINLOG_UNSAFE_ROUTINE,
+ ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
+ result= SP_INTERNAL_ERROR;
+ }
+ else
+ {
+ if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
+ result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
+ else
+ result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
+ }
}
switch (result)
{
case SP_OK:
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4237,6 +4291,12 @@ unsent_create_error:
switch (result)
{
case SP_OK:
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4495,6 +4555,7 @@ unsent_create_error:
break;
}
thd->proc_info="query end";
+ /* Two binlog-related cleanups: */
if (thd->one_shot_set)
{
/*
@@ -5410,9 +5471,14 @@ new_create_field(THD *thd, char *field_name, enum_field_types type,
}
new_field->pack_length=
my_decimal_get_binary_size(new_field->length, new_field->decimals);
- if (new_field->length <= DECIMAL_MAX_LENGTH &&
+ if (new_field->length <= DECIMAL_MAX_PRECISION &&
new_field->length >= new_field->decimals)
+ {
+ new_field->length=
+ my_decimal_precision_to_length(new_field->length, new_field->decimals,
+ type_modifier & UNSIGNED_FLAG);
break;
+ }
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(NULL);
case MYSQL_TYPE_VARCHAR:
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 56d09d7c563..b36d835a80a 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -135,7 +135,8 @@ find_prepared_statement(THD *thd, ulong id, const char *where)
if (stmt == 0 || stmt->type() != Item_arena::PREPARED_STATEMENT)
{
char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf),
+ where);
return 0;
}
return (Prepared_statement *) stmt;
@@ -1006,7 +1007,7 @@ static int mysql_test_update(Prepared_statement *stmt,
if (!open_tables(thd, &table_list, &table_count))
{
- if (table_list->ancestor && table_list->ancestor->next_local)
+ if (table_list->multitable_view)
{
DBUG_ASSERT(table_list->view != 0);
DBUG_PRINT("info", ("Switch to multi-update"));
@@ -1095,8 +1096,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
bool res;
if (!table_list->table)
{
- DBUG_ASSERT(table_list->view &&
- table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(-1);
@@ -1458,8 +1457,6 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
return res;
if (!tables->table)
{
- DBUG_ASSERT(tables->view &&
- tables->ancestor && tables->ancestor->next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
tables->view_db.str, tables->view_name.str);
return -1;
@@ -1969,7 +1966,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
ulong stmt_id= uint4korr(packet);
ulong flags= (ulong) ((uchar) packet[4]);
- Cursor *cursor= 0;
+ Cursor *cursor;
/*
Query text for binary log, or empty string if the query is not put into
binary log.
@@ -1995,6 +1992,13 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
DBUG_VOID_RETURN;
}
+ cursor= stmt->cursor;
+ if (cursor && cursor->is_open())
+ {
+ my_error(ER_EXEC_STMT_WITH_OPEN_CURSOR, MYF(0));
+ DBUG_VOID_RETURN;
+ }
+
DBUG_ASSERT(thd->free_list == NULL);
mysql_reset_thd_for_next_command(thd);
if (flags & (ulong) CURSOR_TYPE_READ_ONLY)
@@ -2013,7 +2017,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
else
{
DBUG_PRINT("info",("Using READ_ONLY cursor"));
- if (!stmt->cursor &&
+ if (!cursor &&
!(cursor= stmt->cursor= new (&stmt->main_mem_root) Cursor()))
DBUG_VOID_RETURN;
/* If lex->result is set, mysql_execute_command will use it */
@@ -2208,13 +2212,15 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
Statement *stmt;
DBUG_ENTER("mysql_stmt_fetch");
- if (!(stmt= thd->stmt_map.find(stmt_id)) ||
- !stmt->cursor ||
- !stmt->cursor->is_open())
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch")))
+ DBUG_VOID_RETURN;
+
+ if (!stmt->cursor || !stmt->cursor->is_open())
{
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_id, "fetch");
+ my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0));
DBUG_VOID_RETURN;
}
+
thd->current_arena= stmt;
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
stmt->cursor->init_thd(thd);
@@ -2223,7 +2229,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
my_pthread_setprio(pthread_self(), QUERY_PRIOR);
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
- (void) stmt->cursor->fetch(num_rows);
+ stmt->cursor->fetch(num_rows);
thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2266,6 +2272,9 @@ void mysql_stmt_reset(THD *thd, char *packet)
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
+ if (stmt->cursor && stmt->cursor->is_open())
+ stmt->cursor->close();
+
stmt->state= Item_arena::PREPARED;
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9b93a92c6aa..5ba157cb608 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -114,17 +114,31 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
static Next_select_func setup_end_select_func(JOIN *join);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc);
-static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
-static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
-static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
-static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records);
-static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static int end_unique_update(JOIN *join,JOIN_TAB *join_tab,
- bool end_of_records);
-static int end_write_group(JOIN *join, JOIN_TAB *join_tab,
- bool end_of_records);
+
+static enum_nested_loop_state
+sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
+ int error, my_bool *report_error);
+static enum_nested_loop_state
+evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab);
+static enum_nested_loop_state
+sub_select(JOIN *join,JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+flush_cached_records(JOIN *join, JOIN_TAB *join_tab, bool skip_last);
+static enum_nested_loop_state
+end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+static enum_nested_loop_state
+end_write_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+
static int test_if_group_changed(List<Item_buff> &list);
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
static int join_read_system(JOIN_TAB *tab);
@@ -1728,6 +1742,7 @@ Cursor::init_from_thd(THD *thd)
/*
XXX: thd->locked_tables is not changed.
What problems can we have with it if cursor is open?
+ TODO: must be fixed because of the prelocked mode.
*/
/*
TODO: grab thd->free_list here?
@@ -1800,13 +1815,7 @@ Cursor::open(JOIN *join_arg)
happen for the first table in join_tab list
*/
DBUG_ASSERT(join_tab->table->null_row == 0);
-
- /*
- There is always at least one record in the table, as otherwise we
- wouldn't have opened the cursor. Therefore a failure is the only
- reason read_first_record can return not 0.
- */
- DBUG_RETURN(join_tab->read_first_record(join_tab));
+ DBUG_RETURN(0);
}
@@ -1816,97 +1825,36 @@ Cursor::open(JOIN *join_arg)
PRECONDITION:
Cursor is open
RETURN VALUES:
- -4 there are more rows, send_eof sent to the client
- 0 no more rows, send_eof was sent to the client, cursor is closed
- other fatal fetch error, cursor is closed (error is not reported)
+ none, this function will send error or OK to network if necessary.
*/
-int
+void
Cursor::fetch(ulong num_rows)
{
THD *thd= join->thd;
JOIN_TAB *join_tab= join->join_tab + join->const_tables;
- COND *on_expr= *join_tab->on_expr_ref;
- COND *select_cond= join_tab->select_cond;
- READ_RECORD *info= &join_tab->read_record;
- int error= 0;
+ enum_nested_loop_state error= NESTED_LOOP_OK;
/* save references to memory, allocated during fetch */
thd->set_n_backup_item_arena(this, &thd->stmt_backup);
join->fetch_limit+= num_rows;
- /*
- Run while there are new rows in the first table;
- For each row, satisfying ON and WHERE clauses (those parts of them which
- can be evaluated early), call next_select.
- */
- do
- {
- int no_more_rows;
-
- join->examined_rows++;
- if (thd->killed) /* Aborted by user */
- {
- my_message(ER_SERVER_SHUTDOWN, ER(ER_SERVER_SHUTDOWN), MYF(0));
- return -1;
- }
-
- if (on_expr == 0 || on_expr->val_int())
- {
- if (select_cond == 0 || select_cond->val_int())
- {
- /*
- TODO: call table->unlock_row() to unlock row failed selection,
- when this feature will be used.
- */
- error= join_tab->next_select(join, join_tab + 1, 0);
- DBUG_ASSERT(error <= 0);
- if (error)
- {
- /* real error or LIMIT/FETCH LIMIT worked */
- if (error == -4)
- {
- /*
- FETCH LIMIT, read ahead one row, and close cursor
- if there is no more rows XXX: to be fixed to support
- non-equi-joins!
- */
- if ((no_more_rows= info->read_record(info)))
- error= no_more_rows > 0 ? -1: 0;
- }
- break;
- }
- }
- }
- /* read next row; break loop if there was an error */
- if ((no_more_rows= info->read_record(info)))
- {
- if (no_more_rows > 0)
- error= -1;
- else
- {
- enum { END_OF_RECORDS= 1 };
- error= join_tab->next_select(join, join_tab+1, (int) END_OF_RECORDS);
- }
- break;
- }
- }
- while (thd->net.report_error == 0);
-
- if (thd->net.report_error)
- error= -1;
-
- if (error == -3) /* LIMIT clause worked */
- error= 0;
+ error= sub_select(join, join_tab, 0);
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
+ error= sub_select(join,join_tab,1);
+ if (error == NESTED_LOOP_QUERY_LIMIT)
+ error= NESTED_LOOP_OK; /* select_limit used */
+ if (error == NESTED_LOOP_CURSOR_LIMIT)
+ join->resume_nested_loop= TRUE;
#ifdef USING_TRANSACTIONS
ha_release_temporary_latches(thd);
#endif
thd->restore_backup_item_arena(this, &thd->stmt_backup);
- if (error == -4)
+ if (error == NESTED_LOOP_CURSOR_LIMIT)
{
/* Fetch limit worked, possibly more rows are there */
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
@@ -1916,20 +1864,15 @@ Cursor::fetch(ulong num_rows)
else
{
close();
- if (error == 0)
+ if (error == NESTED_LOOP_OK)
{
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
}
- else
+ else if (error != NESTED_LOOP_KILLED)
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- /* free cursor memory */
- free_items(free_list);
- free_list= 0;
- free_root(&main_mem_root, MYF(0));
}
- return error;
}
@@ -1968,6 +1911,13 @@ Cursor::close()
}
join= 0;
unit= 0;
+ free_items(free_list);
+ free_list= 0;
+ /*
+ Must be last, as some memory might be allocated for free purposes,
+ like in free_tmp_table() (TODO: fix this issue)
+ */
+ free_root(mem_root, MYF(0));
DBUG_VOID_RETURN;
}
@@ -1976,12 +1926,6 @@ Cursor::~Cursor()
{
if (is_open())
close();
- free_items(free_list);
- /*
- Must be last, as some memory might be allocated for free purposes,
- like in free_tmp_table() (TODO: fix this issue)
- */
- free_root(&main_mem_root, MYF(0));
}
/*********************************************************************/
@@ -2546,8 +2490,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
KEY_OPTIMIZE_EXISTS) |
((old->optimize | new_fields->optimize) &
KEY_OPTIMIZE_REF_OR_NULL));
- old->null_rejecting= old->null_rejecting &&
- new_fields->null_rejecting;
+ old->null_rejecting= (old->null_rejecting &&
+ new_fields->null_rejecting);
}
}
else if (old->eq_func && new_fields->eq_func &&
@@ -2559,8 +2503,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
KEY_OPTIMIZE_EXISTS) |
((old->optimize | new_fields->optimize) &
KEY_OPTIMIZE_REF_OR_NULL));
- old->null_rejecting= old->null_rejecting &&
- new_fields->null_rejecting;
+ old->null_rejecting= (old->null_rejecting &&
+ new_fields->null_rejecting);
}
else if (old->eq_func && new_fields->eq_func &&
(old->val->is_null() || new_fields->val->is_null()))
@@ -2572,7 +2516,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
if (old->val->is_null())
old->val= new_fields->val;
/* The referred expression can be NULL: */
- old->null_rejecting= false;
+ old->null_rejecting= 0;
}
else
{
@@ -2734,6 +2678,8 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
If the condition has form "tbl.keypart = othertbl.field" and
othertbl.field can be NULL, there will be no matches if othertbl.field
has NULL value.
+ We use null_rejecting in add_not_null_conds() to add
+ 'othertbl.field IS NOT NULL' to tab->select_cond.
*/
(*key_fields)->null_rejecting= (cond->functype() == Item_func::EQ_FUNC) &&
((*value)->type() == Item::FIELD_ITEM) &&
@@ -5455,10 +5401,15 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
tab->select_cond=sel->cond=tmp;
if (thd->variables.engine_condition_pushdown)
{
+ COND *push_cond=
+ make_cond_for_table(cond,current_map,current_map);
tab->table->file->pushed_cond= NULL;
- /* Push condition to handler */
- if (!tab->table->file->cond_push(tmp))
- tab->table->file->pushed_cond= tmp;
+ if (push_cond)
+ {
+ /* Push condition to handler */
+ if (!tab->table->file->cond_push(push_cond))
+ tab->table->file->pushed_cond= push_cond;
+ }
}
}
else
@@ -5582,13 +5533,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
thd->memdup((gptr) sel, sizeof(SQL_SELECT));
tab->cache.select->cond=tmp;
tab->cache.select->read_tables=join->const_table_map;
- if (thd->variables.engine_condition_pushdown &&
- (!tab->table->file->pushed_cond))
- {
- /* Push condition to handler */
- if (!tab->table->file->cond_push(tmp))
- tab->table->file->pushed_cond= tmp;
- }
}
}
}
@@ -6487,10 +6431,13 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal)
{
bool copyfl;
- if (field_item->result_type() == STRING_RESULT &&
- ((Field_str *) field_item->field)->charset() !=
- ((Item_cond *) item)->compare_collation())
- return FALSE;
+ if (field_item->result_type() == STRING_RESULT)
+ {
+ CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
+ if ((cs != ((Item_cond *) item)->compare_collation()) ||
+ !cs->coll->propagate(cs, 0, 0))
+ return FALSE;
+ }
Item_equal *item_equal = find_item_equal(cond_equal,
field_item->field, &copyfl);
@@ -7351,7 +7298,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
*/
if (table->on_expr)
{
- Item *expr;
+ Item *expr= table->prep_on_expr ? table->prep_on_expr : table->on_expr;
/*
If an on expression E is attached to the table,
check all null rejected predicates in this expression.
@@ -7361,7 +7308,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
the corresponding on expression is added to E.
*/
expr= simplify_joins(join, &nested_join->join_list,
- table->on_expr, FALSE);
+ expr, FALSE);
table->prep_on_expr= table->on_expr= expr;
}
nested_join->used_tables= (table_map) 0;
@@ -7396,6 +7343,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
if (conds)
{
conds= and_conds(conds, table->on_expr);
+ conds->top_level_item();
/* conds is always a new item as both cond and on_expr existed */
DBUG_ASSERT(!conds->fixed);
conds->fix_fields(join->thd, 0, &conds);
@@ -7832,9 +7780,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
new_field= item->make_string_field(table);
break;
case DECIMAL_RESULT:
- new_field= new Field_new_decimal(item->max_length - (item->decimals?1:0),
- maybe_null,
- item->name, table, item->decimals);
+ new_field= new Field_new_decimal(item->max_length, maybe_null, item->name,
+ table, item->decimals, item->unsigned_flag);
break;
case ROW_RESULT:
default:
@@ -8004,20 +7951,20 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
temp_pool_slot = bitmap_set_next(&temp_pool);
if (temp_pool_slot != MY_BIT_NONE) // we got a slot
- sprintf(filename, "%s_%lx_%i", tmp_file_prefix,
- current_pid, temp_pool_slot);
+ sprintf(path, "%s_%lx_%i", tmp_file_prefix,
+ current_pid, temp_pool_slot);
else
{
/* if we run out of slots or we are not using tempool */
- sprintf(filename,"%s%lx_%lx_%x",tmp_file_prefix,current_pid,
+ sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid,
thd->thread_id, thd->tmp_table++);
}
/*
- No need for change table name to lower case as we are only creating
+ No need to change table name to lower case as we are only creating
MyISAM or HEAP tables here
*/
- sprintf(path, "%s%s", mysql_tmpdir, filename);
+ fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME);
if (group)
{
@@ -8948,7 +8895,8 @@ static Next_select_func setup_end_select_func(JOIN *join)
static int
do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
- int error= 0;
+ int rc= 0;
+ enum_nested_loop_state error= NESTED_LOOP_OK;
JOIN_TAB *join_tab;
DBUG_ENTER("do_select");
@@ -8978,24 +8926,30 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (!join->conds || join->conds->val_int())
{
Next_select_func end_select= join->join_tab[join->tables-1].next_select;
- if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
- error=(*end_select)(join,join_tab,1);
+ error= (*end_select)(join,join_tab,0);
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
+ error= (*end_select)(join,join_tab,1);
}
else if (join->send_row_on_empty_set())
- error= join->result->send_data(*join->fields);
+ rc= join->result->send_data(*join->fields);
}
else
{
error= sub_select(join,join_tab,0);
- if (error >= 0)
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
error= sub_select(join,join_tab,1);
- if (error == -3)
- error= 0; /* select_limit used */
+ if (error == NESTED_LOOP_QUERY_LIMIT)
+ error= NESTED_LOOP_OK; /* select_limit used */
}
+ if (error == NESTED_LOOP_NO_MORE_ROWS)
+ error= NESTED_LOOP_OK;
- if (error >= 0)
+ if (error == NESTED_LOOP_OK)
{
- error=0;
+ /*
+ Sic: this branch works even if rc != 0, e.g. when
+ send_data above returns an error.
+ */
if (!table) // If sending data to client
{
/*
@@ -9004,10 +8958,12 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
*/
join->join_free(0); // Unlock all cursors
if (join->result->send_eof())
- error= 1; // Don't send error
+ rc= 1; // Don't send error
}
DBUG_PRINT("info",("%ld records output",join->send_records));
}
+ else
+ rc= -1;
if (table)
{
int tmp, new_errno= 0;
@@ -9025,40 +8981,42 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
table->file->print_error(new_errno,MYF(0));
}
#ifndef DBUG_OFF
- if (error)
+ if (rc)
{
DBUG_PRINT("error",("Error: do_select() failed"));
}
#endif
- DBUG_RETURN(join->thd->net.report_error ? -1 : error);
+ DBUG_RETURN(join->thd->net.report_error ? -1 : rc);
}
-static int
+static enum_nested_loop_state
sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
- int error;
+ enum_nested_loop_state rc;
if (end_of_records)
{
- if ((error=flush_cached_records(join,join_tab,FALSE)) < 0)
- return error; /* purecov: inspected */
- return sub_select(join,join_tab,end_of_records);
+ rc= flush_cached_records(join,join_tab,FALSE);
+ if (rc == NESTED_LOOP_OK || rc == NESTED_LOOP_NO_MORE_ROWS)
+ rc= sub_select(join,join_tab,end_of_records);
+ return rc;
}
if (join->thd->killed) // If aborted by user
{
join->thd->send_kill_message();
- return -2; /* purecov: inspected */
+ return NESTED_LOOP_KILLED; /* purecov: inspected */
}
if (join_tab->use_quick != 2 || test_if_quick_select(join_tab) <= 0)
{
if (!store_record_in_cache(&join_tab->cache))
- return 0; // There is more room in cache
+ return NESTED_LOOP_OK; // There is more room in cache
return flush_cached_records(join,join_tab,FALSE);
}
- if ((error=flush_cached_records(join,join_tab,TRUE)) < 0)
- return error; /* purecov: inspected */
- return sub_select(join,join_tab,end_of_records); /* Use ordinary select */
+ rc= flush_cached_records(join, join_tab, TRUE);
+ if (rc == NESTED_LOOP_OK || rc == NESTED_LOOP_NO_MORE_ROWS)
+ rc= sub_select(join, join_tab, end_of_records);
+ return rc;
}
/*
@@ -9170,11 +9128,10 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
table of the embedding nested join, if any.
RETURN
- 0, if success
- # of the error, otherwise
+ return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
*/
-static int
+static enum_nested_loop_state
sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
join_tab->table->null_row=0;
@@ -9182,206 +9139,258 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
return (*join_tab->next_select)(join,join_tab+1,end_of_records);
int error;
- JOIN_TAB *first_unmatched;
- JOIN_TAB *tab;
- /* Cache variables for faster loop */
- COND *select_cond= join_tab->select_cond;
+ enum_nested_loop_state rc;
my_bool *report_error= &(join->thd->net.report_error);
+ READ_RECORD *info= &join_tab->read_record;
- join->return_tab= join_tab;
-
- if (join_tab->last_inner)
+ if (join->resume_nested_loop)
{
- /* join_tab is the first inner table for an outer join operation. */
+ /* If not the last table, plunge down the nested loop */
+ if (join_tab < join->join_tab + join->tables - 1)
+ rc= (*join_tab->next_select)(join, join_tab + 1, 0);
+ else
+ {
+ join->resume_nested_loop= FALSE;
+ rc= NESTED_LOOP_OK;
+ }
+ }
+ else
+ {
+ join->return_tab= join_tab;
+
+ if (join_tab->last_inner)
+ {
+ /* join_tab is the first inner table for an outer join operation. */
- /* Set initial state of guard variables for this table.*/
- join_tab->found=0;
- join_tab->not_null_compl= 1;
+ /* Set initial state of guard variables for this table.*/
+ join_tab->found=0;
+ join_tab->not_null_compl= 1;
- /* Set first_unmatched for the last inner table of this group */
- join_tab->last_inner->first_unmatched= join_tab;
+ /* Set first_unmatched for the last inner table of this group */
+ join_tab->last_inner->first_unmatched= join_tab;
+ }
+ join->thd->row_count= 0;
+
+ error= (*join_tab->read_first_record)(join_tab);
+ rc= evaluate_join_record(join, join_tab, error, report_error);
}
- if (!(error=(*join_tab->read_first_record)(join_tab)))
+ while (rc == NESTED_LOOP_OK)
{
- bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
- bool not_used_in_distinct=join_tab->not_used_in_distinct;
- ha_rows found_records=join->found_records;
- READ_RECORD *info= &join_tab->read_record;
+ error= info->read_record(info);
+ rc= evaluate_join_record(join, join_tab, error, report_error);
+ }
- join->thd->row_count= 0;
- do
+ if (rc == NESTED_LOOP_NO_MORE_ROWS &&
+ join_tab->last_inner && !join_tab->found)
+ rc= evaluate_null_complemented_join_record(join, join_tab);
+
+ if (rc == NESTED_LOOP_NO_MORE_ROWS)
+ rc= NESTED_LOOP_OK;
+ return rc;
+}
+
+
+/*
+ Process one record of the nested loop join.
+
+ DESCRIPTION
+ This function will evaluate parts of WHERE/ON clauses that are
+ applicable to the partial record on hand and in case of success
+ submit this record to the next level of the nested loop.
+*/
+
+static enum_nested_loop_state
+evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
+ int error, my_bool *report_error)
+{
+ bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
+ bool not_used_in_distinct=join_tab->not_used_in_distinct;
+ ha_rows found_records=join->found_records;
+ COND *select_cond= join_tab->select_cond;
+
+ if (error > 0 || (*report_error)) // Fatal error
+ return NESTED_LOOP_ERROR;
+ if (error < 0)
+ return NESTED_LOOP_NO_MORE_ROWS;
+ if (join->thd->killed) // Aborted by user
+ {
+ join->thd->send_kill_message();
+ return NESTED_LOOP_KILLED; /* purecov: inspected */
+ }
+ DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
+ if (!select_cond || select_cond->val_int())
+ {
+ /*
+ There is no select condition or the attached pushed down
+ condition is true => a match is found.
+ */
+ bool found= 1;
+ while (join_tab->first_unmatched && found)
{
- if (join->thd->killed) // Aborted by user
- {
- join->thd->send_kill_message();
- return -2; /* purecov: inspected */
- }
- DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
- if (!select_cond || select_cond->val_int())
+ /*
+ The while condition is always false if join_tab is not
+ the last inner join table of an outer join operation.
+ */
+ JOIN_TAB *first_unmatched= join_tab->first_unmatched;
+ /*
+ Mark that a match for current outer table is found.
+ This activates push down conditional predicates attached
+ to the all inner tables of the outer join.
+ */
+ first_unmatched->found= 1;
+ for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
{
- /*
- There is no select condition or the attached pushed down
- condition is true => a match is found.
- */
- bool found= 1;
- while (join_tab->first_unmatched && found)
+ /* Check all predicates that has just been activated. */
+ /*
+ Actually all predicates non-guarded by first_unmatched->found
+ will be re-evaluated again. It could be fixed, but, probably,
+ it's not worth doing now.
+ */
+ if (tab->select_cond && !tab->select_cond->val_int())
{
- /*
- The while condition is always false if join_tab is not
- the last inner join table of an outer join operation.
- */
- first_unmatched= join_tab->first_unmatched;
- /*
- Mark that a match for current outer table is found.
- This activates push down conditional predicates attached
- to the all inner tables of the outer join.
- */
- first_unmatched->found= 1;
- for (tab= first_unmatched; tab <= join_tab; tab++)
- {
- /* Check all predicates that has just been activated. */
+ /* The condition attached to table tab is false */
+ if (tab == join_tab)
+ found= 0;
+ else
+ {
/*
- Actually all predicates non-guarded by first_unmatched->found
- will be re-evaluated again. It could be fixed, but, probably,
- it's not worth doing now.
- */
- if (tab->select_cond && !tab->select_cond->val_int())
- {
- /* The condition attached to table tab is false */
- if (tab == join_tab)
- found= 0;
- else
- {
- /*
- Set a return point if rejected predicate is attached
- not to the last table of the current nest level.
- */
- join->return_tab= tab;
- return 0;
- }
- }
+ Set a return point if rejected predicate is attached
+ not to the last table of the current nest level.
+ */
+ join->return_tab= tab;
+ return NESTED_LOOP_OK;
}
- /*
- Check whether join_tab is not the last inner table
- for another embedding outer join.
- */
- if ((first_unmatched= first_unmatched->first_upper) &&
- first_unmatched->last_inner != join_tab)
- first_unmatched= 0;
- join_tab->first_unmatched= first_unmatched;
}
-
- /*
- It was not just a return to lower loop level when one
- of the newly activated predicates is evaluated as false
- (See above join->return_tab= tab).
- */
- join->examined_rows++;
- join->thd->row_count++;
-
- if (found)
- {
- if (not_exists_optimize)
- break;
- /* A match from join_tab is found for the current partial join. */
- if ((error=(*join_tab->next_select)(join, join_tab+1, 0)) < 0)
- return error;
- if (join->return_tab < join_tab)
- return 0;
- /*
- Test if this was a SELECT DISTINCT query on a table that
- was not in the field list; In this case we can abort if
- we found a row, as no new rows can be added to the result.
- */
- if (not_used_in_distinct && found_records != join->found_records)
- return 0;
- }
- else
- info->file->unlock_row();
}
- else
- {
- /*
- The condition pushed down to the table join_tab rejects all rows
- with the beginning coinciding with the current partial join.
- */
- join->examined_rows++;
- join->thd->row_count++;
- }
-
- } while (!(error=info->read_record(info)) && !(*report_error));
- }
- if (error > 0 || (*report_error)) // Fatal error
- return -1;
-
- if (join_tab->last_inner && !join_tab->found)
- {
- /*
- The table join_tab is the first inner table of a outer join operation
- and no matches has been found for the current outer row.
- */
- JOIN_TAB *last_inner_tab= join_tab->last_inner;
- for ( ; join_tab <= last_inner_tab ; join_tab++)
- {
- /* Change the the values of guard predicate variables. */
- join_tab->found= 1;
- join_tab->not_null_compl= 0;
- /* The outer row is complemented by nulls for each inner tables */
- restore_record(join_tab->table,s->default_values); // Make empty record
- mark_as_null_row(join_tab->table); // For group by without error
- select_cond= join_tab->select_cond;
- /* Check all attached conditions for inner table rows. */
- if (select_cond && !select_cond->val_int())
- return 0;
- }
- join_tab--;
- /*
- The row complemented by nulls might be the first row
- of embedding outer joins.
- If so, perform the same actions as in the code
- for the first regular outer join row above.
- */
- for ( ; ; )
- {
- first_unmatched= join_tab->first_unmatched;
+ /*
+ Check whether join_tab is not the last inner table
+ for another embedding outer join.
+ */
if ((first_unmatched= first_unmatched->first_upper) &&
first_unmatched->last_inner != join_tab)
first_unmatched= 0;
join_tab->first_unmatched= first_unmatched;
- if (!first_unmatched)
- break;
- first_unmatched->found= 1;
- for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
- {
- if (tab->select_cond && !tab->select_cond->val_int())
- {
- join->return_tab= tab;
- return 0;
- }
- }
}
+
/*
- The row complemented by nulls satisfies all conditions
- attached to inner tables.
- Send the row complemented by nulls to be joined with the
- remaining tables.
- */
- if ((error=(*join_tab->next_select)(join, join_tab+1 ,0)) < 0)
- return error;
+ It was not just a return to lower loop level when one
+ of the newly activated predicates is evaluated as false
+ (See above join->return_tab= tab).
+ */
+ join->examined_rows++;
+ join->thd->row_count++;
+
+ if (found)
+ {
+ enum enum_nested_loop_state rc;
+ if (not_exists_optimize)
+ return NESTED_LOOP_NO_MORE_ROWS;
+ /* A match from join_tab is found for the current partial join. */
+ rc= (*join_tab->next_select)(join, join_tab+1, 0);
+ if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
+ return rc;
+ if (join->return_tab < join_tab)
+ return NESTED_LOOP_OK;
+ /*
+ Test if this was a SELECT DISTINCT query on a table that
+ was not in the field list; In this case we can abort if
+ we found a row, as no new rows can be added to the result.
+ */
+ if (not_used_in_distinct && found_records != join->found_records)
+ return NESTED_LOOP_OK;
+ }
+ else
+ join_tab->read_record.file->unlock_row();
}
- return 0;
+ else
+ {
+ /*
+ The condition pushed down to the table join_tab rejects all rows
+ with the beginning coinciding with the current partial join.
+ */
+ join->examined_rows++;
+ join->thd->row_count++;
+ }
+ return NESTED_LOOP_OK;
}
-static int
+/*
+ DESCRIPTION
+ Construct a NULL complimented partial join record and feed it to the next
+ level of the nested loop. This function is used in case we have
+ an OUTER join and no matching record was found.
+*/
+
+static enum_nested_loop_state
+evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab)
+{
+ /*
+ The table join_tab is the first inner table of a outer join operation
+ and no matches has been found for the current outer row.
+ */
+ JOIN_TAB *last_inner_tab= join_tab->last_inner;
+ /* Cache variables for faster loop */
+ COND *select_cond;
+ for ( ; join_tab <= last_inner_tab ; join_tab++)
+ {
+ /* Change the the values of guard predicate variables. */
+ join_tab->found= 1;
+ join_tab->not_null_compl= 0;
+ /* The outer row is complemented by nulls for each inner tables */
+ restore_record(join_tab->table,s->default_values); // Make empty record
+ mark_as_null_row(join_tab->table); // For group by without error
+ select_cond= join_tab->select_cond;
+ /* Check all attached conditions for inner table rows. */
+ if (select_cond && !select_cond->val_int())
+ return NESTED_LOOP_OK;
+ }
+ join_tab--;
+ /*
+ The row complemented by nulls might be the first row
+ of embedding outer joins.
+ If so, perform the same actions as in the code
+ for the first regular outer join row above.
+ */
+ for ( ; ; )
+ {
+ JOIN_TAB *first_unmatched= join_tab->first_unmatched;
+ if ((first_unmatched= first_unmatched->first_upper) &&
+ first_unmatched->last_inner != join_tab)
+ first_unmatched= 0;
+ join_tab->first_unmatched= first_unmatched;
+ if (!first_unmatched)
+ break;
+ first_unmatched->found= 1;
+ for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
+ {
+ if (tab->select_cond && !tab->select_cond->val_int())
+ {
+ join->return_tab= tab;
+ return NESTED_LOOP_OK;
+ }
+ }
+ }
+ /*
+ The row complemented by nulls satisfies all conditions
+ attached to inner tables.
+ Send the row complemented by nulls to be joined with the
+ remaining tables.
+ */
+ return (*join_tab->next_select)(join, join_tab+1, 0);
+}
+
+
+static enum_nested_loop_state
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
{
+ enum_nested_loop_state rc= NESTED_LOOP_OK;
int error;
READ_RECORD *info;
if (!join_tab->cache.records)
- return 0; /* Nothing to do */
+ return NESTED_LOOP_OK; /* Nothing to do */
if (skip_last)
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
if (join_tab->use_quick == 2)
@@ -9396,7 +9405,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
if ((error=join_init_read_record(join_tab)))
{
reset_cache_write(&join_tab->cache);
- return -error; /* No records or error */
+ return error < 0 ? NESTED_LOOP_NO_MORE_ROWS: NESTED_LOOP_ERROR;
}
for (JOIN_TAB *tmp=join->join_tab; tmp != join_tab ; tmp++)
@@ -9411,11 +9420,11 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
if (join->thd->killed)
{
join->thd->send_kill_message();
- return -2; // Aborted by user /* purecov: inspected */
+ return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
}
SQL_SELECT *select=join_tab->select;
- if (!error && (!join_tab->cache.select ||
- !join_tab->cache.select->skip_record()))
+ if (rc == NESTED_LOOP_OK &&
+ (!join_tab->cache.select || !join_tab->cache.select->skip_record()))
{
uint i;
reset_cache_read(&join_tab->cache);
@@ -9423,11 +9432,14 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
{
read_cached_record(join_tab);
if (!select || !select->skip_record())
- if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
+ {
+ rc= (join_tab->next_select)(join,join_tab+1,0);
+ if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
{
reset_cache_write(&join_tab->cache);
- return error; /* purecov: inspected */
+ return rc;
}
+ }
}
}
} while (!(error=info->read_record(info)));
@@ -9436,10 +9448,10 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
read_cached_record(join_tab); // Restore current record
reset_cache_write(&join_tab->cache);
if (error > 0) // Fatal error
- return -1; /* purecov: inspected */
+ return NESTED_LOOP_ERROR; /* purecov: inspected */
for (JOIN_TAB *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
tmp2->table->status=tmp2->status;
- return 0;
+ return NESTED_LOOP_OK;
}
@@ -9905,13 +9917,32 @@ join_read_next_same_or_null(READ_RECORD *info)
/*****************************************************************************
- The different end of select functions
- These functions returns < 0 when end is reached, 0 on ok and > 0 if a
- fatal error (like table corruption) was detected
+ DESCRIPTION
+ Functions that end one nested loop iteration. Different functions
+ are used to support GROUP BY clause and to redirect records
+ to a table (e.g. in case of SELECT into a temporary table) or to the
+ network client.
+
+ RETURN VALUES
+ NESTED_LOOP_OK - the record has been successfully handled
+ NESTED_LOOP_ERROR - a fatal error (like table corruption)
+ was detected
+ NESTED_LOOP_KILLED - thread shutdown was requested while processing
+ the record
+ NESTED_LOOP_QUERY_LIMIT - the record has been successfully handled;
+ additionally, the nested loop produced the
+ number of rows specified in the LIMIT clause
+ for the query
+ NESTED_LOOP_CURSOR_LIMIT - the record has been successfully handled;
+ additionally, there is a cursor and the nested
+ loop algorithm produced the number of rows
+ that is specified for current cursor fetch
+ operation.
+ All return values except NESTED_LOOP_OK abort the nested loop.
*****************************************************************************/
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -9920,14 +9951,14 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
int error;
if (join->having && join->having->val_int() == 0)
- DBUG_RETURN(0); // Didn't match having
+ DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having
error=0;
if (join->procedure)
error=join->procedure->send_row(*join->fields);
else if (join->do_send_rows)
error=join->result->send_data(*join->fields);
if (error)
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if (++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
@@ -9961,10 +9992,10 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
join->do_send_rows= 0;
if (join->unit->fake_select_lex)
join->unit->fake_select_lex->select_limit= HA_POS_ERROR;
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
- DBUG_RETURN(-3); // Abort nicely
+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
}
else if (join->send_records >= join->fetch_limit)
{
@@ -9972,20 +10003,20 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
There is a server side cursor and all rows for
this fetch request are sent.
*/
- DBUG_RETURN(-4);
+ DBUG_RETURN(NESTED_LOOP_CURSOR_LIMIT);
}
}
else
{
if (join->procedure && join->procedure->end_of_records())
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -10037,14 +10068,14 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
}
if (error > 0)
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
if (join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
- DBUG_RETURN(-3); // Abort nicely
+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
join->do_send_rows=0;
join->unit->select_limit_cnt = HA_POS_ERROR;
}
@@ -10054,14 +10085,14 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
There is a server side cursor and all rows
for this fetch request are sent.
*/
- DBUG_RETURN(-4);
+ DBUG_RETURN(NESTED_LOOP_CURSOR_LIMIT);
}
}
}
else
{
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
@@ -10069,33 +10100,32 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
copy_fields(&join->tmp_table_param);
if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
if (update_sum_func(join->sum_funcs))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
TABLE *table=join->tmp_table;
- int error;
DBUG_ENTER("end_write");
if (join->thd->killed) // Aborted by user
{
join->thd->send_kill_message();
- DBUG_RETURN(-2); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
if (!end_of_records)
{
@@ -10120,6 +10150,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
#endif
if (!join->having || join->having->val_int())
{
+ int error;
join->found_records++;
if ((error=table->file->write_row(table->record[0])))
{
@@ -10128,28 +10159,28 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
goto end;
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
error,1))
- DBUG_RETURN(-1); // Not a table_is_full error
+ DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
table->s->uniques=0; // To ensure rows are the same
}
if (++join->send_records >= join->tmp_table_param.end_write_records &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
- DBUG_RETURN(-3);
+ DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
join->do_send_rows=0;
join->unit->select_limit_cnt = HA_POS_ERROR;
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
}
end:
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* Group by searching after group record and updating it if possible */
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -10159,11 +10190,11 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_ENTER("end_update");
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
if (join->thd->killed) // Aborted by user
{
join->thd->send_kill_message();
- DBUG_RETURN(-2); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
join->found_records++;
@@ -10187,9 +10218,9 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/*
@@ -10211,19 +10242,19 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
error, 0))
- DBUG_RETURN(-1); // Not a table_is_full error
+ DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
/* Change method to update rows */
table->file->ha_index_init(0);
join->join_tab[join->tables-1].next_select=end_unique_update;
}
join->send_records++;
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* Like end_update, but this is done with unique constraints instead of keys */
-static int
+static enum_nested_loop_state
end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
@@ -10232,11 +10263,11 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_ENTER("end_unique_update");
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
if (join->thd->killed) // Aborted by user
{
join->thd->send_kill_message();
- DBUG_RETURN(-2); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
init_tmptable_sum_functions(join->sum_funcs);
@@ -10250,12 +10281,12 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if ((int) table->file->get_dup_key(error) < 0)
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
if (table->file->rnd_pos(table->record[1],table->file->dupp_ref))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
restore_record(table,record[1]);
update_tmptable_sum_func(join->sum_funcs,table);
@@ -10263,27 +10294,26 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
/* ARGSUSED */
-static int
+static enum_nested_loop_state
end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
{
TABLE *table=join->tmp_table;
- int error;
int idx= -1;
DBUG_ENTER("end_write_group");
if (join->thd->killed)
{ // Aborted by user
join->thd->send_kill_message();
- DBUG_RETURN(-2); /* purecov: inspected */
+ DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
if (!join->first_record || end_of_records ||
(idx=test_if_group_changed(join->group_fields)) >= 0)
@@ -10302,28 +10332,27 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
copy_sum_funcs(join->sum_funcs,
join->sum_funcs_end[send_group_parts]);
- if (join->having && join->having->val_int() == 0)
- error= -1;
- else if ((error= table->file->write_row(table->record[0])))
+ if (!join->having || join->having->val_int())
{
- if (create_myisam_from_heap(join->thd, table,
- &join->tmp_table_param,
- error, 0))
- DBUG_RETURN(-1);
+ int error= table->file->write_row(table->record[0]);
+ if (error && create_myisam_from_heap(join->thd, table,
+ &join->tmp_table_param,
+ error, 0))
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
if (join->rollup.state != ROLLUP::STATE_NONE)
{
if (join->rollup_write_data((uint) (idx+1), table))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
else
{
if (end_of_records)
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
@@ -10332,17 +10361,17 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
copy_fields(&join->tmp_table_param);
copy_funcs(join->tmp_table_param.items_to_copy);
if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
}
if (update_sum_func(join->sum_funcs))
- DBUG_RETURN(-1);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure)
join->procedure->add();
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
@@ -10971,7 +11000,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
*/
if (!(select->quick= (tab->type == JT_FT ?
new FT_SELECT(thd, table, tab->ref.key) :
- get_quick_select_for_ref(thd, table, &tab->ref))))
+ get_quick_select_for_ref(thd, table, &tab->ref,
+ tab->found_records))))
goto err;
}
}
@@ -11623,11 +11653,13 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
enum enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
for (store_key **copy=ref->key_copy ; *copy ; copy++)
+ {
if ((*copy)->copy())
{
thd->count_cuted_fields= save_count_cuted_fields;
return 1; // Something went wrong
}
+ }
thd->count_cuted_fields= save_count_cuted_fields;
return 0;
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index c9a9b26d1b4..49ac58e913b 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -17,7 +17,7 @@
/* classes to use when handling where clause */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -91,7 +91,15 @@ enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
class JOIN;
-typedef int (*Next_select_func)(JOIN *,struct st_join_table *,bool);
+enum enum_nested_loop_state
+{
+ NESTED_LOOP_KILLED= -2, NESTED_LOOP_ERROR= -1,
+ NESTED_LOOP_OK= 0, NESTED_LOOP_NO_MORE_ROWS= 1,
+ NESTED_LOOP_QUERY_LIMIT= 3, NESTED_LOOP_CURSOR_LIMIT= 4
+};
+
+typedef enum_nested_loop_state
+(*Next_select_func)(JOIN *, struct st_join_table *, bool);
typedef int (*Read_record_func)(struct st_join_table *tab);
@@ -162,6 +170,11 @@ class JOIN :public Sql_alloc
uint send_group_parts;
bool sort_and_group,first_record,full_join,group, no_field_update;
bool do_send_rows;
+ /*
+ TRUE when we want to resume nested loop iterations when
+ fetching data from a cursor
+ */
+ bool resume_nested_loop;
table_map const_table_map,found_const_table_map,outer_join;
ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
/*
@@ -263,6 +276,7 @@ class JOIN :public Sql_alloc
sort_and_group= 0;
first_record= 0;
do_send_rows= 1;
+ resume_nested_loop= FALSE;
send_records= 0;
found_records= 0;
fetch_limit= HA_POS_ERROR;
@@ -350,6 +364,10 @@ class JOIN :public Sql_alloc
/*
Server-side cursor (now stands only for basic read-only cursor)
See class implementation in sql_select.cc
+ A cursor has its own runtime state - list of used items and memory root of
+ used memory - which is different from Prepared statement runtime: it must
+ be different at least for the purpose of reusing the same prepared
+ statement for many cursors.
*/
class Cursor: public Sql_alloc, public Item_arena
@@ -374,7 +392,7 @@ public:
void reset_thd(THD *thd);
int open(JOIN *join);
- int fetch(ulong num_rows);
+ void fetch(ulong num_rows);
void reset() { join= 0; }
bool is_open() const { return join != 0; }
void close();
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d6027699257..dfdff8ae914 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1600,6 +1600,8 @@ LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
/* INFORMATION_SCHEMA name */
LEX_STRING information_schema_name= {(char*)"information_schema", 18};
+
+/* This is only used internally, but we need it here as a forward reference */
extern ST_SCHEMA_TABLE schema_tables[];
typedef struct st_index_field_values
@@ -1693,8 +1695,8 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
CHARSET_INFO *cs= system_charset_info;
ST_SCHEMA_TABLE *schema_table= table->schema_table;
ST_FIELD_INFO *field_info= schema_table->fields_info;
- const char *field_name1= field_info[schema_table->idx_field1].field_name;
- const char *field_name2= field_info[schema_table->idx_field2].field_name;
+ const char *field_name1= schema_table->idx_field1 >= 0 ? field_info[schema_table->idx_field1].field_name : "";
+ const char *field_name2= schema_table->idx_field2 >= 0 ? field_info[schema_table->idx_field2].field_name : "";
if (table->table != item_field->field->table ||
(cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
(uchar *) item_field->field_name,
@@ -1777,32 +1779,77 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
/*
- Add 'information_schema' name to db_names list
+ Create db names list. Information schema name always is first in list
SYNOPSIS
- schema_db_add()
+ make_db_list()
thd thread handler
files list of db names
wild wild string
+ idx_field_vals idx_field_vals->db_name contains db name or
+ wild string
with_i_schema returns 1 if we added 'IS' name to list
otherwise returns 0
+ is_wild_value if value is 1 then idx_field_vals->db_name is
+ wild string otherwise it's db name;
RETURN
1 error
0 success
*/
-int schema_db_add(THD *thd, List<char> *files,
- const char *wild, bool *with_i_schema)
+int make_db_list(THD *thd, List<char> *files,
+ INDEX_FIELD_VALUES *idx_field_vals,
+ bool *with_i_schema, bool is_wild_value)
{
+ LEX *lex= thd->lex;
*with_i_schema= 0;
- if (!wild || !wild_compare(information_schema_name.str, wild, 0))
+ get_index_field_values(lex, idx_field_vals);
+ if (is_wild_value)
{
- *with_i_schema= 1;
- if (files->push_back(thd->strdup(information_schema_name.str)))
- return 1;
+ /*
+ This part of code is only for SHOW DATABASES command.
+ idx_field_vals->db_value can be 0 when we don't use
+ LIKE clause (see also get_index_field_values() function)
+ */
+ if (!idx_field_vals->db_value ||
+ !wild_case_compare(system_charset_info,
+ information_schema_name.str,
+ idx_field_vals->db_value))
+ {
+ *with_i_schema= 1;
+ if (files->push_back(thd->strdup(information_schema_name.str)))
+ return 1;
+ }
+ return mysql_find_files(thd, files, NullS, mysql_data_home,
+ idx_field_vals->db_value, 1);
}
- return 0;
+
+ /*
+ This part of code is for SHOW TABLES, SHOW TABLE STATUS commands.
+ idx_field_vals->db_value can't be 0 (see get_index_field_values()
+ function). lex->orig_sql_command can be not equal to SQLCOM_END
+ only in case of executing of SHOW commands.
+ */
+ if (lex->orig_sql_command != SQLCOM_END)
+ {
+ if (!my_strcasecmp(system_charset_info, information_schema_name.str,
+ idx_field_vals->db_value))
+ {
+ *with_i_schema= 1;
+ return files->push_back(thd->strdup(information_schema_name.str));
+ }
+ return files->push_back(thd->strdup(idx_field_vals->db_value));
+ }
+
+ /*
+ Create list of existing databases. It is used in case
+ of select from information schema table
+ */
+ if (files->push_back(thd->strdup(information_schema_name.str)))
+ return 1;
+ *with_i_schema= 1;
+ return mysql_find_files(thd, files, NullS, mysql_data_home, NullS, 1);
}
@@ -1880,14 +1927,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (schema_table_idx == SCH_TABLES)
lock_type= TL_READ;
- get_index_field_values(lex, &idx_field_vals);
-
- /* information schema name always is first in list */
- if (schema_db_add(thd, &bases, idx_field_vals.db_value, &with_i_schema))
- goto err;
- if (mysql_find_files(thd, &bases, NullS, mysql_data_home,
- idx_field_vals.db_value, 1))
+ if (make_db_list(thd, &bases, &idx_field_vals,
+ &with_i_schema, 0))
goto err;
partial_cond= make_cond_for_info_schema(cond, tables);
@@ -2000,11 +2042,12 @@ err:
bool store_schema_shemata(THD* thd, TABLE *table, const char *db_name,
- const char* cs_name)
+ CHARSET_INFO *cs)
{
restore_record(table, s->default_values);
table->field[1]->store(db_name, strlen(db_name), system_charset_info);
- table->field[2]->store(cs_name, strlen(cs_name), system_charset_info);
+ table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
+ table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
return schema_table_store_record(thd, table);
}
@@ -2022,20 +2065,17 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
TABLE *table= tables->table;
DBUG_ENTER("fill_schema_shemata");
- get_index_field_values(thd->lex, &idx_field_vals);
- /* information schema name always is first in list */
- if (schema_db_add(thd, &files, idx_field_vals.db_value, &with_i_schema))
- DBUG_RETURN(1);
- if (mysql_find_files(thd, &files, NullS, mysql_data_home,
- idx_field_vals.db_value, 1))
+ if (make_db_list(thd, &files, &idx_field_vals,
+ &with_i_schema, 1))
DBUG_RETURN(1);
+
List_iterator_fast<char> it(files);
while ((file_name=it++))
{
if (with_i_schema) // information schema name is always first in list
{
if (store_schema_shemata(thd, table, file_name,
- system_charset_info->csname))
+ system_charset_info))
DBUG_RETURN(1);
with_i_schema= 0;
continue;
@@ -2060,7 +2100,7 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
strmov(path+length, MY_DB_OPT_FILE);
load_db_opt(thd, path, &create);
if (store_schema_shemata(thd, table, file_name,
- create.default_table_charset->csname))
+ create.default_table_charset))
DBUG_RETURN(1);
}
}
@@ -2300,10 +2340,11 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
uint col_access;
check_access(thd,SELECT_ACL | EXTRA_ACL, base_name,
&tables->grant.privilege, 0, 0);
- col_access= get_column_grant(thd, &tables->grant, tables->db,
- tables->table_name,
+ col_access= get_column_grant(thd, &tables->grant,
+ base_name, file_name,
field->field_name) & COL_ACLS;
- if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS && !col_access)
+ if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS &&
+ !tables->schema_table && !col_access)
continue;
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
{
@@ -2313,11 +2354,16 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
end=strmov(end,grant_types.type_names[bitnr]);
}
}
+ if (tables->schema_table) // any user has 'select' privilege on all
+ // I_S table columns
+ table->field[17]->store(grant_types.type_names[0],
+ strlen(grant_types.type_names[0]), cs);
+ else
+ table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
+
#else
*end= 0;
#endif
- table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
-
table->field[1]->store(base_name, strlen(base_name), cs);
table->field[2]->store(file_name, strlen(file_name), cs);
table->field[3]->store(field->field_name, strlen(field->field_name),
@@ -2362,10 +2408,10 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
strlen((const char*) pos), cs);
if (field->has_charset())
{
- table->field[8]->store((longlong) field->representation_length()/
+ table->field[8]->store((longlong) field->field_length/
field->charset()->mbmaxlen);
table->field[8]->set_notnull();
- table->field[9]->store((longlong) field->representation_length());
+ table->field[9]->store((longlong) field->field_length);
table->field[9]->set_notnull();
}
@@ -2373,7 +2419,8 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
uint dec =field->decimals();
switch (field->type()) {
case FIELD_TYPE_NEWDECIMAL:
- table->field[10]->store((longlong) field->field_length);
+ table->field[10]->store((longlong)
+ ((Field_new_decimal*)field)->precision);
table->field[10]->set_notnull();
table->field[11]->store((longlong) field->decimals());
table->field[11]->set_notnull();
@@ -3481,6 +3528,7 @@ ST_FIELD_INFO schema_fields_info[]=
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
{"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
{"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
{"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 7ece9885040..c05305d9265 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -16,7 +16,7 @@
/* This file is originally from the mysql distribution. Coded by monty */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 18c90d549ec..ad0a0baae2d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -38,6 +38,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
+static bool prepare_blob_field(THD *thd, create_field *sql_field);
/*
delete (drop) tables.
@@ -700,21 +701,20 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
String conv, *tmp;
for (uint i= 0; (tmp= it++); i++)
{
+ uint lengthsp;
if (String::needs_conversion(tmp->length(), tmp->charset(),
cs, &dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
- char *buf= (char*) sql_alloc(conv.length()+1);
- memcpy(buf, conv.ptr(), conv.length());
- buf[conv.length()]= '\0';
- interval->type_names[i]= buf;
+ interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
+ conv.length());
interval->type_lengths[i]= conv.length();
}
// Strip trailing spaces.
- uint lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
- interval->type_lengths[i]);
+ lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
+ interval->type_lengths[i]);
interval->type_lengths[i]= lengthsp;
((uchar *)interval->type_names[i])[lengthsp]= '\0';
}
@@ -781,37 +781,8 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
sql_field->create_length_to_internal_length();
- if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
- !(sql_field->flags & BLOB_FLAG))
- {
- /* Convert long VARCHAR columns to TEXT or BLOB */
- char warn_buff[MYSQL_ERRMSG_SIZE];
-
- if (sql_field->def)
- {
- my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
- MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
- DBUG_RETURN(-1);
- }
- sql_field->sql_type= FIELD_TYPE_BLOB;
- sql_field->flags|= BLOB_FLAG;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
- "VARCHAR",
- (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
- warn_buff);
- }
-
- if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
- {
- if (sql_field->sql_type == FIELD_TYPE_BLOB)
- {
- /* The user has given a length to the blob column */
- sql_field->sql_type= get_blob_type_from_length(sql_field->length);
- sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
- }
- sql_field->length= 0; // Probably from an item
- }
+ if (prepare_blob_field(thd, sql_field))
+ DBUG_RETURN(-1);
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
@@ -1352,6 +1323,59 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/*
+ Extend long VARCHAR fields to blob & prepare field if it's a blob
+
+ SYNOPSIS
+ prepare_blob_field()
+ sql_field Field to check
+
+ RETURN
+ 0 ok
+ 1 Error (sql_field can't be converted to blob)
+ In this case the error is given
+*/
+
+static bool prepare_blob_field(THD *thd, create_field *sql_field)
+{
+ DBUG_ENTER("prepare_blob_field");
+
+ if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
+ !(sql_field->flags & BLOB_FLAG))
+ {
+ /* Convert long VARCHAR columns to TEXT or BLOB */
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+
+ if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES)))
+ {
+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
+ MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
+ DBUG_RETURN(1);
+ }
+ sql_field->sql_type= FIELD_TYPE_BLOB;
+ sql_field->flags|= BLOB_FLAG;
+ sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
+ (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
+ (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
+ warn_buff);
+ }
+
+ if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
+ {
+ if (sql_field->sql_type == FIELD_TYPE_BLOB)
+ {
+ /* The user has given a length to the blob column */
+ sql_field->sql_type= get_blob_type_from_length(sql_field->length);
+ sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
+ }
+ sql_field->length= 0;
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
Preparation of create_field for SP function return values.
Based on code used in the inner loop of mysql_prepare_table() above
@@ -1395,33 +1419,12 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
FIELDFLAG_TREAT_BIT_AS_CHAR;
}
sql_field->create_length_to_internal_length();
+ DBUG_ASSERT(sql_field->def == 0);
+ /* Can't go wrong as sql_field->def is not defined */
+ (void) prepare_blob_field(thd, sql_field);
+}
- if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
- !(sql_field->flags & BLOB_FLAG))
- {
- /* Convert long VARCHAR columns to TEXT or BLOB */
- char warn_buff[MYSQL_ERRMSG_SIZE];
- sql_field->sql_type= FIELD_TYPE_BLOB;
- sql_field->flags|= BLOB_FLAG;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
- "VARCHAR",
- (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
- warn_buff);
- }
-
- if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
- {
- if (sql_field->sql_type == FIELD_TYPE_BLOB)
- {
- /* The user has given a length to the blob column */
- sql_field->sql_type= get_blob_type_from_length(sql_field->length);
- sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
- }
- sql_field->length= 0; // Probably from an item
- }
-}
/*
Create a table
@@ -2342,6 +2345,13 @@ send_result_message:
}
close_thread_tables(thd);
table->table=0; // For query cache
+ /*
+ thd->lex->derived_tables may be set to non zero value if we open
+ a view. It is necessary to clear thd->lex->derived_tables flag
+ to prevent processing of derived tables during next open_and_lock_tables
+ if next table is a real table.
+ */
+ thd->lex->derived_tables= 0;
if (protocol->write())
goto err;
}
@@ -2550,6 +2560,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
reg_ext, NullS);
/* Resolve symlinks (for windows) */
fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME));
+ if (lower_case_table_names)
+ my_casedn_str(files_charset_info, src_path);
if (access(src_path, F_OK))
{
my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index c2cd0d59cc3..722568e7f53 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -183,7 +183,7 @@ TEST_join(JOIN *join)
else if (tab->select->quick)
{
fprintf(DBUG_FILE, " quick select used:\n");
- tab->select->quick->dbug_dump(18, false);
+ tab->select->quick->dbug_dump(18, FALSE);
}
else
VOID(fputs(" select used\n",DBUG_FILE));
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 5b6f12eab52..670c618bec5 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -28,7 +28,7 @@ static File_option triggers_file_parameters[]=
mysql_create_or_drop_trigger()
thd - current thread context (including trigger definition in LEX)
tables - table list containing one table for which trigger is created.
- create - whenever we create (true) or drop (false) trigger
+ create - whenever we create (TRUE) or drop (FALSE) trigger
NOTE
This function is mainly responsible for opening and locking of table and
@@ -98,6 +98,21 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (wait_if_global_read_lock(thd, 0, 0))
DBUG_RETURN(TRUE);
+ /*
+ There is no DETERMINISTIC clause for triggers, so can't check it.
+ But a trigger can in theory be used to do nasty things (if it supported
+ DROP for example) so we do the check for privileges. For now there is
+ already a stronger test above (see start of the function); but when this
+ stronger test will be removed, the test below will hold.
+ */
+ if (!trust_routine_creators && mysql_bin_log.is_open() &&
+ !(thd->master_access & SUPER_ACL))
+ {
+ my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
+ ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
VOID(pthread_mutex_lock(&LOCK_open));
result= (create ?
table->triggers->create_trigger(thd, tables):
@@ -109,7 +124,16 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
start_waiting_global_read_lock(thd);
if (!result)
- send_ok(thd);
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ /* Such a statement can always go directly to binlog, no trans cache */
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
DBUG_RETURN(result);
}
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index 7dd6734eb89..90c906fc72f 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -52,7 +52,15 @@ public:
FIXME: We should juggle with security context here (because trigger
should be invoked with creator rights).
*/
+ /*
+ We disable binlogging, as in SP/functions, even though currently
+ triggers can't do updates. When triggers can do updates, someone
+ should add such a trigger to rpl_sp.test to verify that the update
+ does NOT go into binlog.
+ */
+ tmp_disable_binlog(thd);
res= bodies[event][time_type]->execute_function(thd, 0, 0, 0);
+ reenable_binlog(thd);
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index 51ea6d4d627..4df3fe0949d 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -17,7 +17,7 @@
/* This file defines structures needed by udf functions */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface
#endif
@@ -67,6 +67,7 @@ class udf_handler :public Sql_alloc
bool get_arguments();
bool fix_fields(THD *thd,struct st_table_list *tlist,Item_result_field *item,
uint arg_count,Item **args);
+ void cleanup();
double val(my_bool *null_value)
{
if (get_arguments())
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 86aa0bf9890..95268c41aed 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -139,7 +139,7 @@ int mysql_update(THD *thd,
if (open_tables(thd, &table_list, &table_count))
DBUG_RETURN(1);
- if (table_list->ancestor && table_list->ancestor->next_local)
+ if (table_list->multitable_view)
{
DBUG_ASSERT(table_list->view != 0);
DBUG_PRINT("info", ("Switch to multi-update"));
@@ -706,9 +706,11 @@ bool mysql_multi_update_prepare(THD *thd)
if (!tl->placeholder() && !tl->schema_table && !using_lock_tables)
tl->table->reginfo.lock_type= tl->lock_type;
}
-
+ }
+ for(tl= table_list; tl; tl= tl->next_local)
+ {
/* Check access privileges for table */
- if (!tl->derived && !tl->belong_to_view)
+ if (!tl->derived)
{
uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL;
if (check_access(thd, want_privilege,
@@ -721,12 +723,10 @@ bool mysql_multi_update_prepare(THD *thd)
/* check single table update for view compound from several tables */
for (tl= table_list; tl; tl= tl->next_local)
{
- if (tl->table == 0)
+ if (tl->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
- DBUG_ASSERT(tl->view &&
- tl->ancestor && tl->ancestor->next_local);
TABLE_LIST *for_update= 0;
- if (tl->check_single_table(&for_update, tables_for_update))
+ if (tl->check_single_table(&for_update, tables_for_update, tl))
{
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
tl->view_db.str, tl->view_name.str);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index ce08763015f..289bf9d28a3 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -717,6 +717,16 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
}
/*
+ Let us set proper lock type for tables of the view's main select
+ since we may want to perform update or insert on view. This won't
+ work for view containing union. But this is ok since we don't
+ allow insert and update on such views anyway.
+ */
+ if (!lex->select_lex.next_select())
+ for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local)
+ tbl->lock_type= table->lock_type;
+
+ /*
If we are opening this view as part of implicit LOCK TABLES, then
this view serves as simple placeholder and we should not continue
further processing.
@@ -756,26 +766,17 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
table->ancestor= view_tables;
/*
- Process upper level tables of view. As far as we do noy suport union
- here we can go through local tables of view most upper SELECT
+ Tables of the main select of the view should be marked as belonging
+ to the same select as original view (again we can use LEX::select_lex
+ for this purprose because we don't support MERGE algorithm for views
+ with unions).
*/
- for(tbl= view_tables;
- tbl;
- tbl= tbl->next_local)
- {
- /* next table should include SELECT_LEX under this table SELECT_LEX */
+ for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local)
tbl->select_lex= table->select_lex;
- /*
- move lock type (TODO: should we issue error in case of TMPTABLE
- algorithm and non-read locking)?
- */
- tbl->lock_type= table->lock_type;
- }
-
- /* multi table view */
- if (view_tables->next_local)
{
+ if (view_tables->next_local)
+ table->multitable_view= TRUE;
/* make nested join structure for view tables */
NESTED_JOIN *nested_join;
if (!(nested_join= table->nested_join=
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 80bf409f7a4..25a78178995 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1409,8 +1409,7 @@ create_function_tail:
sp->m_returns_cs= new_field->charset;
- if (new_field->sql_type == FIELD_TYPE_SET ||
- new_field->sql_type == FIELD_TYPE_ENUM)
+ if (new_field->interval_list.elements)
{
new_field->interval=
sp->create_typelib(&new_field->interval_list);
@@ -4001,7 +4000,15 @@ select_option:
YYABORT;
Lex->lock_option= TL_READ_HIGH_PRIORITY;
}
- | DISTINCT { Select->options|= SELECT_DISTINCT; }
+ | DISTINCT
+ {
+ if (Select->options & SELECT_ALL)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ Select->options|= SELECT_DISTINCT;
+ }
| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
| SQL_BUFFER_RESULT
@@ -4021,7 +4028,15 @@ select_option:
{
Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
}
- | ALL {}
+ | ALL
+ {
+ if (Select->options & SELECT_DISTINCT)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ Select->options|= SELECT_ALL;
+ }
;
select_lock_type:
@@ -4459,8 +4474,6 @@ simple_expr:
{ $$= new Item_func_export_set($3, $5, $7, $9); }
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')'
{ $$= new Item_func_export_set($3, $5, $7, $9, $11); }
- | FALSE_SYM
- { $$= new Item_int((char*) "FALSE",0,1); }
| FORMAT_SYM '(' expr ',' NUM ')'
{ $$= new Item_func_format($3,atoi($5.str)); }
| FROM_UNIXTIME '(' expr ')'
@@ -4619,8 +4632,6 @@ simple_expr:
{ $$= new Item_func_trim($5,$3); }
| TRUNCATE_SYM '(' expr ',' expr ')'
{ $$= new Item_func_round($3,$5,1); }
- | TRUE_SYM
- { $$= new Item_int((char*) "TRUE",1,1); }
| ident '.' ident '(' udf_expr_list ')'
{
LEX *lex= Lex;
@@ -6835,6 +6846,8 @@ literal:
| NUM_literal { $$ = $1; }
| NULL_SYM { $$ = new Item_null();
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
+ | FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); }
+ | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); }
| HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);}
| BIN_NUM { $$= new Item_bin_string($1.str, $1.length); }
| UNDERSCORE_CHARSET HEX_NUM
diff --git a/sql/table.cc b/sql/table.cc
index 8e0f52e1910..82a8afd826b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -59,6 +59,7 @@ static byte* get_field_name(Field **buff,uint *length,
3 Wrong data in .frm file
4 Error (see frm_error)
5 Error (see frm_error: charset unavailable)
+ 6 Unknown .frm version
*/
int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
@@ -135,10 +136,14 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
*fn_ext(share->table_name)='\0'; // Remove extension
*fn_ext(share->path)='\0'; // Remove extension
- if (head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
- ! (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4)))
+ if (head[0] != (uchar) 254 || head[1] != 1)
+ goto err; /* purecov: inspected */
+ if (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+ ! (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
+ {
+ error= 6;
goto err; /* purecov: inspected */
+ }
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 17;
@@ -1084,6 +1089,12 @@ static void frm_error(int error, TABLE *form, const char *name,
MYF(0), csname, real_name);
break;
}
+ case 6:
+ my_printf_error(ER_NOT_FORM_FILE,
+ "Table '%-.64s' was created with a different version "
+ "of MySQL and cannot be read",
+ MYF(0), name);
+ break;
default: /* Better wrong error than none */
case 4:
my_error(ER_NOT_FORM_FILE, errortype,
@@ -1644,11 +1655,13 @@ void st_table_list::set_ancestor()
*/
tbl->ancestor->set_ancestor();
}
- tbl->table->grant= grant;
+ if (tbl->multitable_view)
+ multitable_view= TRUE;
+ if (tbl->table)
+ tbl->table->grant= grant;
} while ((tbl= tbl->next_local));
- /* if view contain only one table, substitute TABLE of it */
- if (!ancestor->next_local)
+ if (!multitable_view)
{
table= ancestor->table;
schema_table= ancestor->schema_table;
@@ -1675,8 +1688,6 @@ void st_table_list::save_and_clear_want_privilege()
}
else
{
- DBUG_ASSERT(tbl->view && tbl->ancestor &&
- tbl->ancestor->next_local);
tbl->save_and_clear_want_privilege();
}
}
@@ -1698,8 +1709,6 @@ void st_table_list::restore_want_privilege()
tbl->table->grant.want_privilege= privilege_backup;
else
{
- DBUG_ASSERT(tbl->view && tbl->ancestor &&
- tbl->ancestor->next_local);
tbl->restore_want_privilege();
}
}
@@ -2053,16 +2062,17 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
{
if (check_option && check_option->val_int() == 0)
{
+ TABLE_LIST *view= (belong_to_view ? belong_to_view : this);
if (ignore_failure)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED),
- view_db.str, view_name.str);
+ view->view_db.str, view->view_name.str);
return(VIEW_CHECK_SKIP);
}
else
{
- my_error(ER_VIEW_CHECK_FAILED, MYF(0), view_db.str, view_name.str);
+ my_error(ER_VIEW_CHECK_FAILED, MYF(0), view->view_db.str, view->view_name.str);
return(VIEW_CHECK_ERROR);
}
}
@@ -2080,13 +2090,15 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
(should be 0 on call, to find table, or point to table for
unique test)
map bit mask of tables
+ view view for which we are looking table
RETURN
FALSE table not found or found only one
TRUE found several tables
*/
-bool st_table_list::check_single_table(st_table_list **table, table_map map)
+bool st_table_list::check_single_table(st_table_list **table, table_map map,
+ st_table_list *view)
{
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
{
@@ -2097,11 +2109,14 @@ bool st_table_list::check_single_table(st_table_list **table, table_map map)
if (*table)
return TRUE;
else
+ {
*table= tbl;
+ tbl->check_option= view->check_option;
+ }
}
}
else
- if (tbl->check_single_table(table, map))
+ if (tbl->check_single_table(table, map, view))
return TRUE;
}
return FALSE;
@@ -2131,7 +2146,7 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
}
else
{
- DBUG_ASSERT(view && ancestor && ancestor->next_local);
+ DBUG_ASSERT(view && ancestor);
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
if (tbl->set_insert_values(mem_root))
return TRUE;
diff --git a/sql/table.h b/sql/table.h
index 0a4a06a75d1..2e397ff95bf 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -436,6 +436,10 @@ typedef struct st_table_list
bool skip_temporary; /* this table shouldn't be temporary */
/* TRUE if this merged view contain auto_increment field */
bool contain_auto_increment;
+#if 0
+#else
+ bool multitable_view; /* TRUE iff this is multitable view */
+#endif
/* FRMTYPE_ERROR if any type is acceptable */
enum frm_type_enum required_type;
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
@@ -454,7 +458,8 @@ typedef struct st_table_list
void print(THD *thd, String *str);
void save_and_clear_want_privilege();
void restore_want_privilege();
- bool check_single_table(st_table_list **table, table_map map);
+ bool check_single_table(st_table_list **table, table_map map,
+ st_table_list *view);
bool set_insert_values(MEM_ROOT *mem_root);
st_table_list *find_underlying_table(TABLE *table);
} TABLE_LIST;
diff --git a/sql/tztime.h b/sql/tztime.h
index 777e521d761..cbf359e8961 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef __GNUC__
+#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class interface */
#endif
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 929ca5c672e..00fc80a25fe 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -504,6 +504,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length);
+ /* Up to forminfo+288 is free to use for additional information */
DBUG_RETURN(0);
} /* pack_header */
@@ -647,7 +648,7 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
{
int error;
Field::utype type;
- uint firstpos,null_count,null_length;
+ uint null_count;
uchar *buff,*null_pos;
TABLE table;
create_field *field;
@@ -671,22 +672,24 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
table.s->db_low_byte_first= handler->low_byte_first();
table.s->blob_ptr_size= portable_sizeof_char_ptr;
- firstpos=reclength;
null_count=0;
if (!(table_options & HA_OPTION_PACK_RECORD))
{
null_fields++; // Need one bit for delete mark
null_count++;
+ *buff|= 1;
}
- bfill(buff,(null_length=(null_fields+7)/8),255);
- null_pos= buff + null_count / 8;
+ null_pos= buff;
List_iterator<create_field> it(create_fields);
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
while ((field=it++))
{
+ /*
+ regfield don't have to be deleted as it's allocated with sql_alloc()
+ */
Field *regfield=make_field((char*) buff+field->offset,field->length,
- null_pos,
+ null_pos + null_count / 8,
null_count & 7,
field->pack_flag,
field->sql_type,
@@ -696,14 +699,17 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
field->interval,
field->field_name,
&table);
- DBUG_ASSERT(regfield);
+ if (!regfield)
+ goto err; // End of memory
if (!(field->flags & NOT_NULL_FLAG))
+ {
+ *regfield->null_ptr|= regfield->null_bit;
null_count++;
+ }
- if ((uint) field->offset < firstpos &&
- regfield->type() != FIELD_TYPE_NULL)
- firstpos= field->offset;
+ if (field->sql_type == FIELD_TYPE_BIT && !f_bit_as_char(field->pack_flag))
+ null_count+= field->length & 7;
type= (Field::utype) MTYP_TYPENR(field->unireg_check);
@@ -730,11 +736,12 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
else
regfield->reset();
- delete regfield;
}
/* Fill not used startpos */
- bfill((byte*) buff+null_length,firstpos-null_length,255);
+ if (null_count)
+ *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1);
+
error=(int) my_write(file,(byte*) buff,(uint) reclength,MYF_RW);
err:
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index ab6691e68b0..e12ff189eaf 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6335,7 +6335,8 @@ static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler =
my_wildcmp_mb,
my_strcasecmp_mb,
my_instr_mb,
- my_hash_sort_simple
+ my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_big5_handler=
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 9f0e334d3a9..56df289158a 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -459,7 +459,8 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
my_wildcmp_bin,
my_strcasecmp_bin,
my_instr_bin,
- my_hash_sort_bin
+ my_hash_sort_bin,
+ my_propagate_simple
};
@@ -474,7 +475,8 @@ static MY_COLLATION_HANDLER my_collation_binary_handler =
my_wildcmp_bin,
my_strcasecmp_bin,
my_instr_bin,
- my_hash_sort_bin
+ my_hash_sort_bin,
+ my_propagate_simple
};
diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c
index 47bf1167c8c..f2f31b1064e 100644
--- a/strings/ctype-cp932.c
+++ b/strings/ctype-cp932.c
@@ -5462,6 +5462,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index f5a410afc50..aaf87e97cb8 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -599,6 +599,7 @@ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
my_strcasecmp_8bit,
my_instr_simple,
my_hash_sort_simple,
+ my_propagate_simple
};
CHARSET_INFO my_charset_latin2_czech_ci =
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index 289b7309ea0..21b7b56fdaa 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8647,6 +8647,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c
index ab12446754a..d9171c800bf 100644
--- a/strings/ctype-eucjpms.c
+++ b/strings/ctype-eucjpms.c
@@ -8648,6 +8648,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index 73e4132dd7f..592ee341781 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5698,6 +5698,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_mb, /* instr */
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index d4f9627ecf7..ec96caa6b91 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -9945,6 +9945,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index fdf9f4a6d91..7a75992dc4f 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -698,7 +698,8 @@ static MY_COLLATION_HANDLER my_collation_german2_ci_handler=
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
- my_hash_sort_latin1_de
+ my_hash_sort_latin1_de,
+ my_propagate_complex
};
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index b603a8ea0a8..b3ec476b8f5 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -920,7 +920,8 @@ MY_COLLATION_HANDLER my_collation_mb_bin_handler =
my_wildcmp_mb_bin,
my_strcasecmp_mb_bin,
my_instr_mb,
- my_hash_sort_mb_bin
+ my_hash_sort_mb_bin,
+ my_propagate_simple
};
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 5fa1a1b18a0..d19326d9265 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1340,6 +1340,60 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)),
}
+/*
+ Check if a constant can be propagated
+
+ SYNOPSIS:
+ my_propagate_simple()
+ cs Character set information
+ str String to convert to double
+ length Optional length for string.
+
+ NOTES:
+ Takes the string in the given charset and check
+ if it can be safely propagated in the optimizer.
+
+ create table t1 (
+ s char(5) character set latin1 collate latin1_german2_ci);
+ insert into t1 values (0xf6); -- o-umlaut
+ select * from t1 where length(s)=1 and s='oe';
+
+ The above query should return one row.
+ We cannot convert this query into:
+ select * from t1 where length('oe')=1 and s='oe';
+
+ Currently we don't check the constant itself,
+ and decide not to propagate a constant
+ just if the collation itself allows tricky things
+ like expansions and contractions. In the future
+ we can write a more sophisticated functions to
+ check the constants. For example, 'oa' can always
+ be safety propagated in German2 because unlike
+ 'oe' it does not have any special meaning.
+
+ RETURN
+ 1 if constant can be safely propagated
+ 0 if it is not safe to propagate the constant
+*/
+
+
+
+my_bool my_propagate_simple(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+ return 1;
+}
+
+
+my_bool my_propagate_complex(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *str __attribute__((unused)),
+ uint length __attribute__((unused)))
+{
+ return 0;
+}
+
+
MY_CHARSET_HANDLER my_charset_8bit_handler=
{
my_cset_init_8bit,
@@ -1380,5 +1434,6 @@ MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler =
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
- my_hash_sort_simple
+ my_hash_sort_simple,
+ my_propagate_simple
};
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 62cb5427dd9..a7d75da42c9 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4591,7 +4591,7 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)),
{
const char *b0= b;
*error= 0;
- while (pos && b < e)
+ while (pos-- && b < e)
{
if ((uchar) b[0] < 128)
{
@@ -4631,6 +4631,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_8bit,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index b6c54f1b375..c40e74c3343 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -933,6 +933,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_8bit,
my_instr_simple, /* QQ: To be fixed */
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 3204bd2e1f6..fb7e93e10b6 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -8029,7 +8029,8 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler =
my_wildcmp_uca,
NULL,
my_instr_mb,
- my_hash_sort_ucs2_uca
+ my_hash_sort_ucs2_uca,
+ my_propagate_complex
};
CHARSET_INFO my_charset_ucs2_general_uca=
@@ -8510,7 +8511,8 @@ MY_COLLATION_HANDLER my_collation_any_uca_handler =
my_wildcmp_uca,
NULL,
my_instr_mb,
- my_hash_sort_any_uca
+ my_hash_sort_any_uca,
+ my_propagate_complex
};
/*
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 73d15da8a4a..d15144b7438 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1527,7 +1527,8 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
my_wildcmp_ucs2_ci,
my_strcasecmp_ucs2,
my_instr_mb,
- my_hash_sort_ucs2
+ my_hash_sort_ucs2,
+ my_propagate_simple
};
@@ -1542,7 +1543,8 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler =
my_wildcmp_ucs2_bin,
my_strcasecmp_ucs2_bin,
my_instr_mb,
- my_hash_sort_ucs2_bin
+ my_hash_sort_ucs2_bin,
+ my_propagate_simple
};
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 7bcf1c83bab..5d0c77cee6e 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8516,6 +8516,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_strcasecmp_mb,
my_instr_mb,
my_hash_sort_simple,
+ my_propagate_simple
};
static MY_CHARSET_HANDLER my_charset_handler=
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index 14b3934e815..250c57cf265 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2316,7 +2316,8 @@ static MY_COLLATION_HANDLER my_collation_ci_handler =
my_wildcmp_utf8,
my_strcasecmp_utf8,
my_instr_mb,
- my_hash_sort_utf8
+ my_hash_sort_utf8,
+ my_propagate_complex
};
MY_CHARSET_HANDLER my_charset_utf8_handler=
@@ -2540,7 +2541,8 @@ static MY_COLLATION_HANDLER my_collation_cs_handler =
my_wildcmp_mb,
my_strcasecmp_utf8,
my_instr_mb,
- my_hash_sort_utf8
+ my_hash_sort_utf8,
+ my_propagate_simple
};
CHARSET_INFO my_charset_utf8_general_cs=
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 8c58520f965..cb8de8f43ac 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -631,7 +631,8 @@ static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
my_wildcmp_8bit,
my_strcasecmp_8bit,
my_instr_simple,
- my_hash_sort_simple
+ my_hash_sort_simple,
+ my_propagate_simple
};
diff --git a/strings/decimal.c b/strings/decimal.c
index 9af95511f6d..1e62333ee66 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -274,20 +274,20 @@ static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
/*
- Remove ending 0 digits from fraction part
+ Count actual length of fraction part (without ending zeroes)
SYNOPSIS
- decimal_optimize_fraction()
+ decimal_actual_fraction()
from number for processing
*/
-void decimal_optimize_fraction(decimal_t *from)
+int decimal_actual_fraction(decimal_t *from)
{
int frac= from->frac, i;
dec1 *buf0= from->buf + ROUND_UP(from->intg) + ROUND_UP(frac) - 1;
if (frac == 0)
- return;
+ return 0;
i= ((frac - 1) % DIG_PER_DEC1 + 1);
while (frac > 0 && *buf0 == 0)
@@ -302,7 +302,7 @@ void decimal_optimize_fraction(decimal_t *from)
*buf0 % powers10[i++] == 0;
frac--);
}
- from->frac= frac;
+ return frac;
}
@@ -332,23 +332,15 @@ int decimal2string(decimal_t *from, char *to, int *to_len,
int fixed_precision, int fixed_decimals,
char filler)
{
- int len, intg, frac=from->frac, i, intg_len, frac_len, fill;
+ int len, intg, frac= from->frac, i, intg_len, frac_len, fill;
/* number digits before decimal point */
int fixed_intg= (fixed_precision ?
- (fixed_precision -
- (from->sign ? 1 : 0) -
- (fixed_decimals ? 1 : 0) -
- fixed_decimals) :
- 0);
+ (fixed_precision - fixed_decimals) : 0);
int error=E_DEC_OK;
char *s=to;
dec1 *buf, *buf0=from->buf, tmp;
DBUG_ASSERT(*to_len >= 2+from->sign);
- DBUG_ASSERT(fixed_precision == 0 ||
- (fixed_precision < *to_len &&
- fixed_precision > ((from->sign ? 1 : 0) +
- (fixed_decimals ? 1 : 0))));
/* removing leading zeroes */
buf0= remove_leading_zeroes(from, &intg);
@@ -1170,6 +1162,8 @@ int decimal2bin(decimal_t *from, char *to, int precision, int frac)
isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
+ const int orig_isize0= isize0;
+ const int orig_fsize0= fsize0;
char *orig_to= to;
buf1= remove_leading_zeroes(from, &from_intg);
@@ -1260,10 +1254,15 @@ int decimal2bin(decimal_t *from, char *to, int precision, int frac)
}
if (fsize0 > fsize1)
{
- while (fsize0-- > fsize1)
+ char *to_end= orig_to + orig_fsize0 + orig_isize0;
+
+ while (fsize0-- > fsize1 && to < to_end)
*to++=(uchar)mask;
}
orig_to[0]^= 0x80;
+
+ /* Check that we have written the whole decimal and nothing more */
+ DBUG_ASSERT(to == orig_to + orig_fsize0 + orig_isize0);
return error;
}
@@ -1620,13 +1619,19 @@ static int do_add(decimal_t *from1, decimal_t *from2, decimal_t *to)
x=intg1 > intg2 ? from1->buf[0] :
intg2 > intg1 ? from2->buf[0] :
from1->buf[0] + from2->buf[0] ;
- if (unlikely(x > DIG_MASK*9)) /* yes, there is */
+ if (unlikely(x > DIG_MAX-1)) /* yes, there is */
{
intg0++;
to->buf[0]=0; /* safety */
}
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
+ if (unlikely(error == E_DEC_OVERFLOW))
+ {
+ max_decimal(to->len * DIG_PER_DEC1, 0, to);
+ return error;
+ }
+
buf0=to->buf+intg0+frac0;
to->sign=from1->sign;
@@ -1711,19 +1716,23 @@ static int do_sub(decimal_t *from1, decimal_t *from2, decimal_t *to)
carry=1;
else if (intg2 == intg1)
{
- while (unlikely(stop1[frac1-1] == 0))
- frac1--;
- while (unlikely(stop2[frac2-1] == 0))
- frac2--;
- while (buf1 < stop1+frac1 && buf2 < stop2+frac2 && *buf1 == *buf2)
+ dec1 *end1= stop1 + (frac1 - 1);
+ dec1 *end2= stop2 + (frac2 - 1);
+ while (unlikely((buf1 <= end1) && (*end1 == 0)))
+ end1--;
+ while (unlikely((buf2 <= end2) && (*end2 == 0)))
+ end2--;
+ frac1= (end1 - stop1) + 1;
+ frac2= (end2 - stop2) + 1;
+ while (buf1 <=end1 && buf2 <= end2 && *buf1 == *buf2)
buf1++, buf2++;
- if (buf1 < stop1+frac1)
- if (buf2 < stop2+frac2)
+ if (buf1 <= end1)
+ if (buf2 <= end2)
carry= *buf2 > *buf1;
else
carry= 0;
else
- if (buf2 < stop2+frac2)
+ if (buf2 <= end2)
carry=1;
else /* short-circuit everything: from1 == from2 */
{
@@ -1922,6 +1931,17 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
for (; carry; buf0--)
ADD(*buf0, *buf0, 0, carry);
}
+
+ /* Now we have to check for -0.000 case */
+ if (to->sign)
+ {
+ dec1 *buf= to->buf;
+ dec1 *end= to->buf + intg0 + frac0;
+ for (; (buf<end) && !*buf; buf++);
+ if (buf == end)
+ /* So we got decimal zero */
+ decimal_make_zero(to);
+ }
return error;
}
@@ -1953,6 +1973,18 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
sanity(to);
/* removing all the leading zeroes */
+ i= ((prec2 - 1) % DIG_PER_DEC1) + 1;
+ while (prec2 > 0 && *buf2 == 0)
+ {
+ prec2-= i;
+ i= DIG_PER_DEC1;
+ buf2++;
+ }
+ if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
+ return E_DEC_DIV_ZERO;
+ for (i= (prec2 - 1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
+ DBUG_ASSERT(prec2 > 0);
+
i=((prec1-1) % DIG_PER_DEC1)+1;
while (prec1 > 0 && *buf1 == 0)
{
@@ -1968,19 +2000,6 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
DBUG_ASSERT(prec1 > 0);
- i=((prec2-1) % DIG_PER_DEC1)+1;
- while (prec2 > 0 && *buf2 == 0)
- {
- prec2-=i;
- i=DIG_PER_DEC1;
- buf2++;
- }
- if (prec2 <= 0) /* short-circuit everything: from2 == 0 */
- return E_DEC_DIV_ZERO;
-
- for (i=(prec2-1) % DIG_PER_DEC1; *buf2 < powers10[i--]; prec2--) ;
- DBUG_ASSERT(prec2 > 0);
-
/* let's fix scale_incr, taking into account frac1,frac2 increase */
if ((scale_incr-= frac1 - from1->frac + frac2 - from2->frac) < 0)
scale_incr=0;
@@ -2609,7 +2628,7 @@ void test_fr(const char *s1, const char *orig)
printf("%-40s => ", s);
end= strend(s1);
string2decimal(s1, &a, &end);
- decimal_optimize_fraction(&a);
+ a.frac= decimal_actual_fraction(&a);
print_decimal(&a, orig, 0, 0);
printf("\n");
}
@@ -2731,6 +2750,7 @@ int main()
test_dv("123", "0.01","12300.000000000", 0);
test_dv("120", "100000000000.00000","0.000000001200000000", 0);
test_dv("123", "0","", 4);
+ test_dv("0", "0", "", 4);
test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000", 0);
test_dv("121931851853376", "987654321","123456.000000000", 0);
test_dv("0", "987","0", 0);
@@ -2947,7 +2967,7 @@ int main()
test_sh("123456789.987654321", 0, "123456789.987654321", 0);
a.len= sizeof(buf1)/sizeof(dec1);
- printf("==== decimal_optimize_fraction ====\n");
+ printf("==== decimal_actual_fraction ====\n");
test_fr("1.123456789000000000", "1.123456789");
test_fr("1.12345678000000000", "1.12345678");
test_fr("1.1234567000000000", "1.1234567");
diff --git a/support-files/MacOSX/mwar-wrapper b/support-files/MacOSX/mwar-wrapper
new file mode 100755
index 00000000000..4bc5153e7ef
--- /dev/null
+++ b/support-files/MacOSX/mwar-wrapper
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# This script can only create a library, not take it apart
+# again to AR files
+
+case $1 in
+ -d*|-m*|-t*|-p*|-r*|-x*|x)
+ echo "$0: can't handle arguments $*"
+ exit 1;
+ ;;
+ -c|c|cr|cru|cu)
+ shift;
+ ;;
+esac
+
+exec mwld -lib -o $*
diff --git a/support-files/MacOSX/mwcc-wrapper b/support-files/MacOSX/mwcc-wrapper
new file mode 100755
index 00000000000..914578aca1d
--- /dev/null
+++ b/support-files/MacOSX/mwcc-wrapper
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+if [ -z "$CWINSTALL" ] ; then
+ echo "ERROR: You need to source 'mwvars' to set CWINSTALL and other variables"
+ exit 1
+fi
+
+if [ `expr "$MWMacOSXPPCLibraryFiles" : ".*BSD.*"` = 0 ] ; then
+ echo "ERROR: You need to source 'mwvars' with the 'bsd' argument"
+ exit 1
+fi
+
+# ==============================================================================
+
+# Extra options that don't change
+
+PREOPTS="-D__SCHAR_MAX__=127 -D__CHAR_BIT__=8 -ext o -gccinc"
+PREOPTS="$PREOPTS -wchar_t on -bool on -relax_pointers -align power_gcc"
+PREOPTS="$PREOPTS -stabs all -fno-handle-exceptions -Cpp_exceptions off"
+
+# ==============================================================================
+
+# We want the "PPC Specific" directory to be last, before the source
+# file. It is to work around a CodeWarrior/Apple bug, that we need a
+# Metrowersk header even though we have configured CodeWarrior to use
+# the BSD headers. But not to conflict, the directory has to be last.
+
+# FIXME this will probably break if one path contains space characters
+
+PREARGS=""
+for i in $* ; do
+ case "$i" in
+ -bind_at_load)
+ # This is a flag some version of libtool adds, when the host
+ # is "*darwin*". It doesn't check that it is gcc.
+ # FIXME add some flag?!
+ ;;
+ *.c|*.cc|*.cpp)
+ break
+ ;;
+ *)
+ PREARGS="$PREARGS $1"
+ ;;
+ esac
+ shift
+done
+#echo "mwcc $PREOPTS $PREARGS -I\"$CWINSTALL/MacOS X Support/Headers/PPC Specific\" $*"
+exec mwcc $PREOPTS $PREARGS -I"$CWINSTALL/MacOS X Support/Headers/PPC Specific" $*
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 071b7696908..6757a1052a8 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -10,7 +10,7 @@
# started and shut down when the systems goes down.
# Comments to support chkconfig on RedHat Linux
-# chkconfig: 2345 90 20
+# chkconfig: 2345 64 36
# description: A very fast and reliable SQL database engine.
# Comments to support LSB init script conventions
diff --git a/tests/index_corrupt.pl b/tests/index_corrupt.pl
new file mode 100755
index 00000000000..19bf54f5d11
--- /dev/null
+++ b/tests/index_corrupt.pl
@@ -0,0 +1,212 @@
+#!/usr/bin/perl -w
+#
+# This is a test for a key cache bug (bug #10167)
+# To expose the bug mysqld should be started with --key-buffer-size=64K
+#
+
+$opt_loop_count=100000; # Change this to make test harder/easier
+
+##################### Standard benchmark inits ##############################
+
+use DBI;
+use Getopt::Long;
+use Benchmark;
+
+package main;
+
+$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
+ $opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
+$opt_host=$opt_user=$opt_password=""; $opt_db="test";
+
+GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in",
+ "skip-delete","verbose","fast-insert","lock-tables","debug","fast",
+ "force","user=s","password=s") || die "Aborted";
+$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
+
+$firsttable = "bench_f1";
+$secondtable = "bench_f2";
+$kill_file= "/tmp/mysqltest_index_corrupt.$$";
+
+####
+#### Start timeing and start test
+####
+
+$start_time=new Benchmark;
+if (!$opt_skip_create)
+{
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+ $dbh->do("drop table if exists $firsttable, $secondtable");
+
+ print "Creating tables in $opt_db\n";
+ $dbh->do("create table $firsttable (
+c_pollid INTEGER NOT NULL,
+c_time BIGINT NOT NULL,
+c_data DOUBLE NOT NULL,
+c_error INTEGER NOT NULL,
+c_warning INTEGER NOT NULL,
+c_okay INTEGER NOT NULL,
+c_unknown INTEGER NOT NULL,
+c_rolled_up BIT NOT NULL,
+INDEX t_mgmt_hist_r_i1 (c_pollid),
+INDEX t_mgmt_hist_r_i2 (c_time),
+INDEX t_mgmt_hist_r_i3 (c_rolled_up))") or die $DBI::errstr;
+
+ $dbh->do("create table $secondtable (
+c_pollid INTEGER NOT NULL,
+c_min_time BIGINT NOT NULL,
+c_max_time BIGINT NOT NULL,
+c_min_data DOUBLE NOT NULL,
+c_max_data DOUBLE NOT NULL,
+c_avg_data DOUBLE NOT NULL,
+c_error INTEGER NOT NULL,
+c_warning INTEGER NOT NULL,
+c_okay INTEGER NOT NULL,
+c_unknown INTEGER NOT NULL,
+c_rolled_up BIT NOT NULL,
+INDEX t_mgmt_hist_d_i1 (c_pollid),
+INDEX t_mgmt_hist_d_i2 (c_min_time),
+INDEX t_mgmt_hist_d_i3 (c_max_time),
+INDEX t_mgmt_hist_d_i4 (c_rolled_up))") or die $DBI::errstr;
+
+
+ $dbh->disconnect; $dbh=0; # Close handler
+}
+$|= 1; # Autoflush
+
+####
+#### Start the tests
+####
+
+print "Running tests\n";
+insert_in_bench() if (($pid=fork()) == 0); $work{$pid}="insert";
+select_from_bench() if (($pid=fork()) == 0); $work{$pid}="insert-select;
+delete_from_bench() if (($pid=fork()) == 0); $work{$pid}="delete";
+
+$errors=0;
+while (($pid=wait()) != -1)
+{
+ $ret=$?/256;
+ print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
+ $errors++ if ($ret != 0);
+}
+
+if (!$opt_skip_delete && !$errors)
+{
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+ $dbh->do("drop table $firsttable, $secondtable");
+}
+print ($errors ? "Test failed\n" :"Test ok\n");
+
+$end_time=new Benchmark;
+print "Total time: " .
+ timestr(timediff($end_time, $start_time),"noc") . "\n";
+
+unlink $kill_file;
+
+exit(0);
+
+#
+# Insert records in the two tables
+#
+
+sub insert_in_bench
+{
+ my ($dbh,$rows,$found,$i);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+ for ($rows= 1; $rows <= $opt_loop_count ; $rows++)
+ {
+ $c_pollid = sprintf("%d",rand 1000);
+ $c_time = sprintf("%d",rand 100000);
+ $c_data = rand 1000000;
+ $test = rand 1;
+ $c_error=0;
+ $c_warning=0;
+ $c_okay=0;
+ $c_unknown=0;
+ if ($test < .8) {
+ $c_okay=1;
+ } elsif ($test <.9) {
+ $c_error=1;
+ } elsif ($test <.95) {
+ $c_warning=1;
+ } else {
+ $c_unknown=1;
+ }
+ $statement = "INSERT INTO $firsttable (c_pollid, c_time, c_data, c_error
+, c_warning, c_okay, c_unknown, c_rolled_up) ".
+ "VALUES ($c_pollid,$c_time,$c_data,$c_error,$c_warning,$c_okay,$c_unknown,0)";
+ $cursor = $dbh->prepare($statement);
+ $cursor->execute();
+ $cursor->finish();
+ }
+
+ $dbh->disconnect; $dbh=0;
+ print "insert_in_bench: Inserted $rows rows\n";
+
+ # Kill other threads
+ open(KILLFILE, "> $kill_file");
+ close(KILLFILE);
+
+ exit(0);
+}
+
+
+sub select_from_bench
+{
+ my ($dbh,$rows,$cursor);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+ for ($rows= 1; $rows < $opt_loop_count ; $rows++)
+ {
+ $t_value = rand 100000;
+ $t_value2 = $t_value+10000;
+ $statement = "INSERT INTO $secondtable (c_pollid, c_min_time, c_max_time
+, c_min_data, c_max_data, c_avg_data, c_error, c_warning, c_okay, c_unknown, c_rolled_up) SELECT c_pollid, MIN(c_time), MAX(c_time), MIN(c_data), MAX(c_data), AVG(c_data), SUM(c_error), SUM(c_warning), SUM(c_okay), SUM(c_unknown), 0 FROM $firsttable WHERE (c_time>=$t_value) AND (c_time<$t_value2) AND (c_rolled_up=0) GROUP BY c_pollid";
+ $cursor = $dbh->prepare($statement);
+ $cursor->execute();
+ $cursor->finish();
+ sleep 1;
+ if (-e $kill_file)
+ {
+ last;
+ }
+ }
+ print "select_from_bench: insert-select executed $rows times\n";
+ exit(0);
+}
+
+
+sub delete_from_bench
+{
+ my ($dbh,$row, $t_value, $t2_value, $statement, $cursor);
+
+ $dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
+ $opt_user, $opt_password,
+ { PrintError => 0}) || die $DBI::errstr;
+
+ for ($rows= 1; $rows < $opt_loop_count ; $rows++)
+ {
+ $t_value = rand 50000;
+ $t2_value = $t_value + 50001;
+ $statement = "DELETE FROM $firsttable WHERE (c_time>$t_value) AND (c_time<$t2_value)";
+ $cursor = $dbh->prepare($statement);
+ $cursor->execute();
+ $cursor->finish();
+ sleep 10;
+ if (-e $kill_file)
+ {
+ last;
+ }
+ }
+ print "delete: delete executed $rows times\n";
+ exit(0);
+}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 9b7c8281043..da57fbabaf2 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -37,6 +37,7 @@
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
#define MAX_KEY 64
+#define MAX_SERVER_ARGS 64
/* set default options */
static int opt_testcase = 0;
@@ -55,6 +56,18 @@ static unsigned int test_count= 0;
static unsigned int opt_count= 0;
static unsigned int iter_count= 0;
+static const char *opt_basedir= "./";
+
+static int embedded_server_arg_count= 0;
+static char *embedded_server_args[MAX_SERVER_ARGS];
+
+static const char *embedded_server_groups[]= {
+ "server",
+ "embedded",
+ "mysql_client_test_SERVER",
+ NullS
+};
+
static time_t start_time, end_time;
static double total_time;
@@ -100,6 +113,8 @@ static void client_disconnect();
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
+#define DIE(expr) \
+ die(__FILE__, __LINE__, #expr)
void die(const char *file, int line, const char *expr)
{
@@ -2254,7 +2269,7 @@ static void test_ps_conj_select()
check_execute(stmt, rc);
int_data= 1;
- strcpy(str_data, "hh");
+ strmov(str_data, "hh");
str_length= strlen(str_data);
rc= mysql_stmt_execute(stmt);
@@ -7046,6 +7061,7 @@ static void test_set_option()
bug #89 (reported by mark@mysql.com)
*/
+#ifndef EMBEDDED_LIBRARY
static void test_prepare_grant()
{
int rc;
@@ -7138,7 +7154,7 @@ static void test_prepare_grant()
}
}
-
+#endif
/*
Test a crash when invalid/corrupted .frm is used in the
@@ -7272,7 +7288,7 @@ static void test_decimal_bug()
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- strcpy(data, "8.0");
+ strmov(data, "8.0");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -7290,7 +7306,7 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
- strcpy(data, "5.61");
+ strmov(data, "5.61");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -7315,7 +7331,7 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
- strcpy(data, "10.22"); is_null= 0;
+ strmov(data, "10.22"); is_null= 0;
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -8494,13 +8510,13 @@ static void test_sqlmode()
myquery(rc);
/* PIPES_AS_CONCAT */
- strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
+ strmov(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
if (!opt_silent)
fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
- strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ strmov(query, "INSERT INTO test_piping VALUES(?||?)");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8526,7 +8542,7 @@ static void test_sqlmode()
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- strcpy(c1, "My"); strcpy(c2, "SQL");
+ strmov(c1, "My"); strmov(c2, "SQL");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -8536,20 +8552,20 @@ static void test_sqlmode()
rc= mysql_query(mysql, "DELETE FROM test_piping");
myquery(rc);
- strcpy(query, "SELECT connection_id ()");
+ strmov(query, "SELECT connection_id ()");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
/* ANSI */
- strcpy(query, "SET SQL_MODE= \"ANSI\"");
+ strmov(query, "SET SQL_MODE= \"ANSI\"");
if (!opt_silent)
fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
- strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
+ strmov(query, "INSERT INTO test_piping VALUES(?||?)");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8560,7 +8576,7 @@ static void test_sqlmode()
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
- strcpy(c1, "My"); strcpy(c2, "SQL");
+ strmov(c1, "My"); strmov(c2, "SQL");
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
@@ -8568,7 +8584,7 @@ static void test_sqlmode()
verify_col_data("test_piping", "name", "MySQL");
/* ANSI mode spaces ... */
- strcpy(query, "SELECT connection_id ()");
+ strmov(query, "SELECT connection_id ()");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -8588,13 +8604,13 @@ static void test_sqlmode()
mysql_stmt_close(stmt);
/* IGNORE SPACE MODE */
- strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
+ strmov(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
if (!opt_silent)
fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
- strcpy(query, "SELECT connection_id ()");
+ strmov(query, "SELECT connection_id ()");
if (!opt_silent)
fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
@@ -9099,7 +9115,7 @@ static void test_bug2248()
/* This too should not hang but should return proper error */
rc= mysql_stmt_fetch(stmt);
- DIE_UNLESS(rc == MYSQL_NO_DATA);
+ DIE_UNLESS(rc == 1);
/* This too should not hang but should not bark */
rc= mysql_stmt_store_result(stmt);
@@ -9108,7 +9124,7 @@ static void test_bug2248()
/* This should return proper error */
rc= mysql_stmt_fetch(stmt);
check_execute_r(stmt, rc);
- DIE_UNLESS(rc == MYSQL_NO_DATA);
+ DIE_UNLESS(rc == 1);
mysql_stmt_close(stmt);
@@ -10250,7 +10266,7 @@ static void test_union_param()
my_bool my_null= FALSE;
myheader("test_union_param");
- strcpy(my_val, "abc");
+ strmov(my_val, "abc");
query= (char*)"select ? as my_col union distinct select ?";
stmt= mysql_simple_prepare(mysql, query);
@@ -10532,14 +10548,14 @@ static void test_bug3796()
if (!opt_silent)
printf("Concat result: '%s'\n", out_buff);
check_execute(stmt, rc);
- strcpy(canonical_buff, concat_arg0);
+ strmov(canonical_buff, concat_arg0);
strcat(canonical_buff, "ONE");
DIE_UNLESS(strlen(canonical_buff) == out_length &&
strncmp(out_buff, canonical_buff, out_length) == 0);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- strcpy(canonical_buff + strlen(concat_arg0), "TWO");
+ strmov(canonical_buff + strlen(concat_arg0), "TWO");
DIE_UNLESS(strlen(canonical_buff) == out_length &&
strncmp(out_buff, canonical_buff, out_length) == 0);
if (!opt_silent)
@@ -10836,7 +10852,8 @@ static void test_view()
rc= mysql_stmt_prepare(stmt, query, strlen(query));
check_execute(stmt, rc);
- strcpy(str_data, "TEST");
+ strmov(str_data, "TEST");
+ bzero(bind, sizeof(bind));
bind[0].buffer_type= FIELD_TYPE_STRING;
bind[0].buffer= (char *)&str_data;
bind[0].buffer_length= 50;
@@ -10955,8 +10972,9 @@ static void test_view_2where()
" AENAME,T0001.DEPENDVARS AS DEPENDVARS,T0001.INACTIVE AS "
" INACTIVE from LTDX T0001 where (T0001.SRTF2 = 0)");
myquery(rc);
+ bzero(bind, sizeof(bind));
for (i=0; i < 8; i++) {
- strcpy(parms[i], "1");
+ strmov(parms[i], "1");
bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
bind[i].buffer = (char *)&parms[i];
bind[i].buffer_length = 100;
@@ -11003,6 +11021,7 @@ static void test_view_star()
myquery(rc);
rc= mysql_query(mysql, "CREATE VIEW vt1 AS SELECT a FROM t1");
myquery(rc);
+ bzero(bind, sizeof(bind));
for (i= 0; i < 2; i++) {
sprintf((char *)&parms[i], "%d", i);
bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
@@ -11068,6 +11087,7 @@ static void test_view_insert()
rc= mysql_stmt_prepare(select_stmt, query, strlen(query));
check_execute(select_stmt, rc);
+ bzero(bind, sizeof(bind));
bind[0].buffer_type = FIELD_TYPE_LONG;
bind[0].buffer = (char *)&my_val;
bind[0].length = &my_length;
@@ -11171,6 +11191,7 @@ static void test_view_insert_fields()
" F7F8 AS F7F8, F6N4 AS F6N4, F5C8 AS F5C8, F9D8 AS F9D8"
" from t1 T0001");
+ bzero(bind, sizeof(bind));
for (i= 0; i < 11; i++)
{
l[i]= 20;
@@ -11178,7 +11199,7 @@ static void test_view_insert_fields()
bind[i].is_null= 0;
bind[i].buffer= (char *)&parm[i];
- strcpy(parm[i], "1");
+ strmov(parm[i], "1");
bind[i].buffer_length= 2;
bind[i].length= &l[i];
}
@@ -12597,7 +12618,7 @@ static void test_bug8330()
const char *stmt_text;
MYSQL_STMT *stmt[2];
int i, rc;
- char *query= "select a,b from t1 where a=?";
+ const char *query= "select a,b from t1 where a=?";
MYSQL_BIND bind[2];
long lval[2];
@@ -12691,6 +12712,7 @@ from t2);");
rc= mysql_query(mysql, "DROP VIEW v1");
myquery(rc);
rc= mysql_query(mysql, "DROP TABLE t1, t2");
+ mysql_free_result(res);
myquery(rc);
}
@@ -12708,7 +12730,7 @@ from t2);");
static void test_bug8378()
{
-#ifdef HAVE_CHARSET_gbk
+#if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
MYSQL *lmysql;
char out[9]; /* strlen(TEST_BUG8378)*2+1 */
int len;
@@ -12788,7 +12810,7 @@ static void test_bug8722()
}
-MYSQL_STMT *open_cursor(char *query)
+MYSQL_STMT *open_cursor(const char *query)
{
int rc;
const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
@@ -12854,6 +12876,205 @@ static void test_bug9159()
myquery(rc);
}
+
+/* Crash when opening a cursor to a query with DISTICNT and no key */
+
+static void test_bug9520()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[6];
+ ulong a_len;
+ int rc, row_count= 0;
+
+ myheader("test_bug9520");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (a char(5), b char(5), c char(5),"
+ " primary key (a, b, c))");
+ rc= mysql_query(mysql, "insert into t1 values ('x', 'y', 'z'), "
+ " ('a', 'b', 'c'), ('k', 'l', 'm')");
+ myquery(rc);
+
+ stmt= open_cursor("select distinct b from t1");
+
+ /*
+ Not crashes with:
+ stmt= open_cursor("select distinct a from t1");
+ */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char*) a;
+ bind[0].buffer_length= sizeof(a);
+ bind[0].length= &a_len;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ while (!(rc= mysql_stmt_fetch(stmt)))
+ row_count++;
+
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ printf("Fetched %d rows\n", row_count);
+ DBUG_ASSERT(row_count == 3);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/*
+ We can't have more than one cursor open for a prepared statement.
+ Test re-executions of a PS with cursor; mysql_stmt_reset must close
+ the cursor attached to the statement, if there is one.
+*/
+
+static void test_bug9478()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char a[6];
+ ulong a_len;
+ int rc, i;
+
+ myheader("test_bug9478");
+
+ mysql_query(mysql, "drop table if exists t1");
+ mysql_query(mysql, "create table t1 (id integer not null primary key, "
+ " name varchar(20) not null)");
+ rc= mysql_query(mysql, "insert into t1 (id, name) values "
+ " (1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
+ myquery(rc);
+
+ stmt= open_cursor("select name from t1 where id=2");
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char*) a;
+ bind[0].buffer_length= sizeof(a);
+ bind[0].length= &a_len;
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 5; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+
+ /*
+ The query above is a one-row result set. Therefore, there is no
+ cursor associated with it, as the server won't bother with opening
+ a cursor for a one-row result set. The first row was read from the
+ server in the fetch above. But there is eof packet pending in the
+ network. mysql_stmt_execute will flush the packet and successfully
+ execute the statement.
+ */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+
+ rc= mysql_stmt_reset(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt));
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
+ }
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ /* Test the case with a server side cursor */
+ stmt= open_cursor("select name from t1");
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ for (i= 0; i < 5; i++)
+ {
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+ /*
+ Although protocol-wise an attempt to execute a statement which
+ already has an open cursor associated with it will yield an error,
+ the client library behavior tested here is consistent with
+ the non-cursor execution scenario: mysql_stmt_execute will
+ silently close the cursor if necessary.
+ */
+ {
+ char buff[9];
+ bzero(buff, sizeof(buff));
+ /* Fill in the execute packet */
+ int4store(buff, stmt->stmt_id);
+ int4store(buff+5, 1);
+ rc= ((*mysql->methods->advanced_command)(mysql, COM_EXECUTE, buff,
+ sizeof(buff), 0,0,1) ||
+ (*mysql->methods->read_query_result)(mysql));
+ DIE_UNLESS(rc);
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_error(mysql));
+ }
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ while (! (rc= mysql_stmt_fetch(stmt)))
+ {
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+ }
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ if (!opt_silent && i == 0)
+ printf("Fetched row: %s\n", a);
+
+ rc= mysql_stmt_reset(stmt);
+ check_execute(stmt, rc);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt));
+ if (!opt_silent && i == 0)
+ printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
+ }
+
+ rc= mysql_stmt_close(stmt);
+ DIE_UNLESS(rc == 0);
+
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -12863,6 +13084,8 @@ static char **defaults_argv;
static struct my_option client_test_long_options[] =
{
+ {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir,
+ (gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"count", 't', "Number of times test to be executed", (char **) &opt_count,
(char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use", (char **) &opt_db, (char **) &opt_db,
@@ -12878,6 +13101,8 @@ static struct my_option client_test_long_options[] =
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection", (char **) &opt_port,
(char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"server-arg", 'A', "Send embedded server this as a parameter.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
{"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0,
@@ -13079,6 +13304,8 @@ static struct my_tests_st my_tests[]= {
{ "test_bug8722", test_bug8722 },
{ "test_bug8880", test_bug8880 },
{ "test_bug9159", test_bug9159 },
+ { "test_bug9520", test_bug9520 },
+ { "test_bug9478", test_bug9478 },
{ 0, 0 }
};
@@ -13113,6 +13340,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
else
opt_silent++;
break;
+ case 'A':
+ /*
+ When the embedded server is being tested, the test suite needs to be
+ able to pass command-line arguments to the embedded server so it can
+ locate the language files and data directory. The test suite
+ (mysql-test-run) never uses config files, just command-line options.
+ */
+ if (!embedded_server_arg_count)
+ {
+ embedded_server_arg_count= 1;
+ embedded_server_args[0]= (char*) "";
+ }
+ if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
+ !(embedded_server_args[embedded_server_arg_count++]=
+ my_strdup(argument, MYF(MY_FAE))))
+ {
+ DIE("Can't use server argument");
+ }
+ break;
case 'T':
{
struct my_tests_st *fptr;
@@ -13176,11 +13422,16 @@ int main(int argc, char **argv)
DEBUGGER_OFF;
MY_INIT(argv[0]);
-
+
load_defaults("my", client_test_load_default_groups, &argc, &argv);
defaults_argv= argv;
get_options(&argc, &argv);
+ if (mysql_server_init(embedded_server_arg_count,
+ embedded_server_args,
+ (char**) embedded_server_groups))
+ DIE("Can't initialize MySQL server");
+
client_connect(); /* connect to server */
total_time= 0;
@@ -13227,6 +13478,12 @@ int main(int argc, char **argv)
client_disconnect(); /* disconnect from server */
free_defaults(defaults_argv);
print_test_output();
+
+ while (embedded_server_arg_count > 1)
+ my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
+
+ mysql_server_end();
+
my_end(0);
exit(0);
diff --git a/vio/vio_priv.h b/vio/vio_priv.h
index 9a925a2c4c9..3a75a08021d 100644
--- a/vio/vio_priv.h
+++ b/vio/vio_priv.h
@@ -23,7 +23,7 @@
#include <m_string.h>
#include <violite.h>
-void vio_ignore_timeout(Vio *vio, uint timeout);
+void vio_ignore_timeout(Vio *vio, uint which, uint timeout);
#ifdef HAVE_OPENSSL
#include "my_net.h" /* needed because of struct in_addr */
@@ -31,7 +31,7 @@ void vio_ignore_timeout(Vio *vio, uint timeout);
void vio_ssl_delete(Vio* vio);
int vio_ssl_read(Vio *vio,gptr buf, int size);
int vio_ssl_write(Vio *vio,const gptr buf,int size);
-void vio_ssl_timeout(Vio *vio, uint timeout);
+void vio_ssl_timeout(Vio *vio, uint which, uint timeout);
/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */
int vio_ssl_fastsend(Vio *vio);
diff --git a/vio/viosocket.c b/vio/viosocket.c
index ea85a69e2d4..ee8e85880ba 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -364,12 +364,14 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
void vio_timeout(Vio *vio __attribute__((unused)),
- uint timeout __attribute__((unused)))
+ uint which __attribute__((unused)),
+ uint timeout __attribute__((unused)))
{
#ifdef __WIN__
ulong wait_timeout= (ulong) timeout * 1000;
- (void) setsockopt(vio->sd, SOL_SOCKET, SO_RCVTIMEO, (char*) &wait_timeout,
- sizeof(wait_timeout));
+ (void) setsockopt(vio->sd, SOL_SOCKET,
+ which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout,
+ sizeof(wait_timeout));
#endif /* __WIN__ */
}
diff --git a/vio/viossl.c b/vio/viossl.c
index 400d8842fd3..4233b276346 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -424,7 +424,8 @@ int vio_ssl_blocking(Vio * vio __attribute__((unused)),
void vio_ssl_timeout(Vio *vio __attribute__((unused)),
- uint timeout __attribute__((unused)))
+ uint which __attribute__((unused)),
+ uint timeout __attribute__((unused)))
{
/* Not yet implemented (non critical) */
}